| ... | @@ -7853,19 +7853,85 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7853,19 +7853,85 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 7853 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | 7853 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; |
| 7854 | switch (result_ty.zigTypeTag()) { | 7854 | switch (result_ty.zigTypeTag()) { |
| 7855 | .Struct => { | 7855 | .Struct => { |
| 7856 | if (result_ty.containerLayout() == .Packed) { | | |
| 7857 | return self.fail("TODO airAggregateInit implement packed structs", .{}); | | |
| 7858 | } | | |
| 7859 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); | 7856 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); |
| 7860 | for (elements, 0..) |elem, elem_i| { | 7857 | const dst_mcv = MCValue{ .stack_offset = stack_offset }; |
| 7861 | if (result_ty.structFieldValueComptime(elem_i) != null) continue; // comptime elem | 7858 | if (result_ty.containerLayout() == .Packed) { |
| | 7859 | const struct_obj = result_ty.castTag(.@"struct").?.data; |
| | 7860 | try self.genInlineMemset( |
| | 7861 | dst_mcv, |
| | 7862 | .{ .immediate = 0 }, |
| | 7863 | .{ .immediate = abi_size }, |
| | 7864 | .{}, |
| | 7865 | ); |
| | 7866 | for (elements, 0..) |elem, elem_i| { |
| | 7867 | if (result_ty.structFieldValueComptime(elem_i) != null) continue; |
| | 7868 | |
| | 7869 | const elem_ty = result_ty.structFieldType(elem_i); |
| | 7870 | const elem_bit_size = @intCast(u32, elem_ty.bitSize(self.target.*)); |
| | 7871 | if (elem_bit_size > 64) { |
| | 7872 | return self.fail("TODO airAggregateInit implement packed structs with large fields", .{}); |
| | 7873 | } |
| | 7874 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| | 7875 | const elem_abi_bits = elem_abi_size * 8; |
| | 7876 | const elem_off = struct_obj.packedFieldBitOffset(self.target.*, elem_i); |
| | 7877 | const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size); |
| | 7878 | const elem_bit_off = elem_off % elem_abi_bits; |
| | 7879 | const elem_mcv = try self.resolveInst(elem); |
| | 7880 | const elem_lock = switch (elem_mcv) { |
| | 7881 | .register => |reg| self.register_manager.lockReg(reg), |
| | 7882 | .immediate => |imm| lock: { |
| | 7883 | if (imm == 0) continue; |
| | 7884 | break :lock null; |
| | 7885 | }, |
| | 7886 | else => null, |
| | 7887 | }; |
| | 7888 | defer if (elem_lock) |lock| self.register_manager.unlockReg(lock); |
| | 7889 | const elem_reg = try self.copyToTmpRegister(elem_ty, elem_mcv); |
| | 7890 | const elem_extra_bits = self.regExtraBits(elem_ty); |
| | 7891 | if (elem_bit_off < elem_extra_bits) { |
| | 7892 | try self.truncateRegister(elem_ty, registerAlias(elem_reg, elem_abi_size)); |
| | 7893 | } |
| | 7894 | if (elem_bit_off > 0) try self.genShiftBinOpMir( |
| | 7895 | .sal, |
| | 7896 | elem_ty, |
| | 7897 | .{ .register = elem_reg }, |
| | 7898 | .{ .immediate = elem_bit_off }, |
| | 7899 | ); |
| | 7900 | try self.genBinOpMir( |
| | 7901 | .@"or", |
| | 7902 | elem_ty, |
| | 7903 | .{ .stack_offset = stack_offset - elem_byte_off }, |
| | 7904 | .{ .register = elem_reg }, |
| | 7905 | ); |
| | 7906 | if (elem_bit_off > elem_extra_bits) { |
| | 7907 | const reg = try self.copyToTmpRegister(elem_ty, elem_mcv); |
| | 7908 | if (elem_extra_bits > 0) { |
| | 7909 | try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size)); |
| | 7910 | } |
| | 7911 | try self.genShiftBinOpMir( |
| | 7912 | .sar, |
| | 7913 | elem_ty, |
| | 7914 | .{ .register = reg }, |
| | 7915 | .{ .immediate = elem_abi_bits - elem_bit_off }, |
| | 7916 | ); |
| | 7917 | try self.genBinOpMir( |
| | 7918 | .@"or", |
| | 7919 | elem_ty, |
| | 7920 | .{ .stack_offset = stack_offset - elem_byte_off - |
| | 7921 | @intCast(i32, elem_abi_size) }, |
| | 7922 | .{ .register = reg }, |
| | 7923 | ); |
| | 7924 | } |
| | 7925 | } |
| | 7926 | } else for (elements, 0..) |elem, elem_i| { |
| | 7927 | if (result_ty.structFieldValueComptime(elem_i) != null) continue; |
| 7862 | | 7928 | |
| 7863 | const elem_ty = result_ty.structFieldType(elem_i); | 7929 | const elem_ty = result_ty.structFieldType(elem_i); |
| 7864 | const elem_off = result_ty.structFieldOffset(elem_i, self.target.*); | 7930 | const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*)); |
| 7865 | const elem_mcv = try self.resolveInst(elem); | 7931 | const elem_mcv = try self.resolveInst(elem); |
| 7866 | try self.genSetStack(elem_ty, stack_offset - @intCast(i32, elem_off), elem_mcv, .{}); | 7932 | try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{}); |
| 7867 | } | 7933 | } |
| 7868 | break :res MCValue{ .stack_offset = stack_offset }; | 7934 | break :res dst_mcv; |
| 7869 | }, | 7935 | }, |
| 7870 | .Array => { | 7936 | .Array => { |
| 7871 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); | 7937 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); |