| ... | @@ -812,7 +812,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void | ... | @@ -812,7 +812,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 812 | const stack_mcv = try self.allocRegOrMem(inst, false); | 812 | const stack_mcv = try self.allocRegOrMem(inst, false); |
| 813 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); | 813 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); |
| 814 | const reg_mcv = self.getResolvedInstValue(inst); | 814 | const reg_mcv = self.getResolvedInstValue(inst); |
| 815 | assert(reg == reg_mcv.register.to64()); | 815 | assert(reg.to64() == reg_mcv.register.to64()); |
| 816 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 816 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 817 | try branch.inst_table.put(self.gpa, inst, stack_mcv); | 817 | try branch.inst_table.put(self.gpa, inst, stack_mcv); |
| 818 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv); | 818 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv); |
| ... | @@ -1791,22 +1791,50 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { | ... | @@ -1791,22 +1791,50 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { |
| 1791 | } | 1791 | } |
| 1792 | | 1792 | |
| 1793 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { | 1793 | fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { |
| 1794 | return if (self.liveness.isUnused(inst)) .dead else result: { | 1794 | if (self.liveness.isUnused(inst)) { |
| 1795 | const mcv = try self.resolveInst(operand); | 1795 | return MCValue.dead; |
| 1796 | const struct_ty = self.air.typeOf(operand).childType(); | 1796 | } |
| 1797 | const struct_size = @intCast(i32, struct_ty.abiSize(self.target.*)); | 1797 | const mcv = try self.resolveInst(operand); |
| 1798 | const struct_field_offset = @intCast(i32, struct_ty.structFieldOffset(index, self.target.*)); | 1798 | const struct_ty = self.air.typeOf(operand).childType(); |
| 1799 | const struct_field_ty = struct_ty.structFieldType(index); | 1799 | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); |
| 1800 | const struct_field_size = @intCast(i32, struct_field_ty.abiSize(self.target.*)); | 1800 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 1801 | | 1801 | const struct_field_ty = struct_ty.structFieldType(index); |
| | 1802 | const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); |
| | 1803 | const offset_to_field = struct_size - struct_field_offset - struct_field_size; |
| | 1804 | |
| | 1805 | const dst_mcv: MCValue = result: { |
| 1802 | switch (mcv) { | 1806 | switch (mcv) { |
| 1803 | .ptr_stack_offset => |off| { | 1807 | .ptr_stack_offset => |off| { |
| 1804 | const ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size; | 1808 | const ptr_stack_offset = off + @intCast(i32, offset_to_field); |
| 1805 | break :result MCValue{ .ptr_stack_offset = ptr_stack_offset }; | 1809 | break :result MCValue{ .ptr_stack_offset = ptr_stack_offset }; |
| 1806 | }, | 1810 | }, |
| | 1811 | .register => |reg| { |
| | 1812 | const offset_reg = try self.copyToTmpRegister(Type.usize, .{ |
| | 1813 | .immediate = offset_to_field, |
| | 1814 | }); |
| | 1815 | self.register_manager.freezeRegs(&.{offset_reg}); |
| | 1816 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); |
| | 1817 | |
| | 1818 | const can_reuse_operand = self.reuseOperand(inst, operand, 0, mcv); |
| | 1819 | const result_reg = blk: { |
| | 1820 | if (can_reuse_operand) { |
| | 1821 | break :blk reg; |
| | 1822 | } else { |
| | 1823 | self.register_manager.freezeRegs(&.{reg}); |
| | 1824 | const result_reg = try self.register_manager.allocReg(inst, &.{}); |
| | 1825 | try self.genSetReg(Type.usize, result_reg, mcv); |
| | 1826 | break :blk result_reg; |
| | 1827 | } |
| | 1828 | }; |
| | 1829 | defer if (!can_reuse_operand) self.register_manager.unfreezeRegs(&.{reg}); |
| | 1830 | |
| | 1831 | try self.genBinMathOpMir(.add, Type.usize, .{ .register = result_reg }, .{ .register = offset_reg }); |
| | 1832 | break :result MCValue{ .register = result_reg }; |
| | 1833 | }, |
| 1807 | else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), | 1834 | else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), |
| 1808 | } | 1835 | } |
| 1809 | }; | 1836 | }; |
| | 1837 | return dst_mcv; |
| 1810 | } | 1838 | } |
| 1811 | | 1839 | |
| 1812 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | 1840 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |