| ... | @@ -886,7 +886,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void | ... | @@ -886,7 +886,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 886 | assert(reg.to64() == reg_mcv.register.to64()); | 886 | assert(reg.to64() == reg_mcv.register.to64()); |
| 887 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 887 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 888 | try branch.inst_table.put(self.gpa, inst, stack_mcv); | 888 | try branch.inst_table.put(self.gpa, inst, stack_mcv); |
| 889 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, .rbp, reg_mcv); | 889 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv, .{}); |
| 890 | } | 890 | } |
| 891 | | 891 | |
| 892 | /// Copies a value to a register without tracking the register. The register is not considered | 892 | /// Copies a value to a register without tracking the register. The register is not considered |
| ... | @@ -1196,8 +1196,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1196,8 +1196,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1196 | const len_ty = self.air.typeOf(bin_op.rhs); | 1196 | const len_ty = self.air.typeOf(bin_op.rhs); |
| 1197 | | 1197 | |
| 1198 | const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16)); | 1198 | const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16)); |
| 1199 | try self.genSetStack(ptr_ty, stack_offset, .rbp, ptr); | 1199 | try self.genSetStack(ptr_ty, stack_offset, ptr, .{}); |
| 1200 | try self.genSetStack(len_ty, stack_offset - 8, .rbp, len); | 1200 | try self.genSetStack(len_ty, stack_offset - 8, len, .{}); |
| 1201 | const result = MCValue{ .stack_offset = stack_offset }; | 1201 | const result = MCValue{ .stack_offset = stack_offset }; |
| 1202 | | 1202 | |
| 1203 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1203 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | @@ -1797,24 +1797,47 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1797,24 +1797,47 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1797 | /// T to E!T | 1797 | /// T to E!T |
| 1798 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { | 1798 | fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1799 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1799 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1800 | const result: MCValue = if (self.liveness.isUnused(inst)) | 1800 | if (self.liveness.isUnused(inst)) { |
| 1801 | .dead | 1801 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1802 | else | 1802 | } |
| 1803 | return self.fail("TODO implement wrap errunion payload for {}", .{self.target.cpu.arch}); | 1803 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 1804 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1804 | const error_ty = error_union_ty.errorUnionSet(); |
| | 1805 | const payload_ty = error_union_ty.errorUnionPayload(); |
| | 1806 | const operand = try self.resolveInst(ty_op.operand); |
| | 1807 | assert(payload_ty.hasRuntimeBits()); |
| | 1808 | |
| | 1809 | const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); |
| | 1810 | const abi_align = error_union_ty.abiAlignment(self.target.*); |
| | 1811 | const err_abi_size = @intCast(u32, error_ty.abiSize(self.target.*)); |
| | 1812 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); |
| | 1813 | try self.genSetStack(error_ty, stack_offset, .{ .immediate = 0 }, .{}); |
| | 1814 | try self.genSetStack(payload_ty, stack_offset - @intCast(i32, err_abi_size), operand, .{}); |
| | 1815 | |
| | 1816 | return self.finishAir(inst, .{ .stack_offset = stack_offset }, .{ ty_op.operand, .none, .none }); |
| 1805 | } | 1817 | } |
| 1806 | | 1818 | |
| 1807 | /// E to E!T | 1819 | /// E to E!T |
| 1808 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | 1820 | fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1809 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1821 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1810 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1822 | if (self.liveness.isUnused(inst)) { |
| 1811 | const error_union_ty = self.air.getRefType(ty_op.ty); | 1823 | return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); |
| 1812 | const payload_ty = error_union_ty.errorUnionPayload(); | 1824 | } |
| 1813 | const mcv = try self.resolveInst(ty_op.operand); | 1825 | const error_union_ty = self.air.getRefType(ty_op.ty); |
| 1814 | if (!payload_ty.hasRuntimeBits()) break :result mcv; | 1826 | const error_ty = error_union_ty.errorUnionSet(); |
| 1815 | | 1827 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1816 | return self.fail("TODO implement wrap errunion error for non-empty payloads", .{}); | 1828 | const err = try self.resolveInst(ty_op.operand); |
| | 1829 | const result: MCValue = result: { |
| | 1830 | if (!payload_ty.hasRuntimeBits()) break :result err; |
| | 1831 | |
| | 1832 | const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*)); |
| | 1833 | const abi_align = error_union_ty.abiAlignment(self.target.*); |
| | 1834 | const err_abi_size = @intCast(u32, error_ty.abiSize(self.target.*)); |
| | 1835 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); |
| | 1836 | try self.genSetStack(error_ty, stack_offset, err, .{}); |
| | 1837 | try self.genSetStack(payload_ty, stack_offset - @intCast(i32, err_abi_size), .undef, .{}); |
| | 1838 | break :result MCValue{ .stack_offset = stack_offset }; |
| 1817 | }; | 1839 | }; |
| | 1840 | |
| 1818 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1841 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1819 | } | 1842 | } |
| 1820 | | 1843 | |
| ... | @@ -1974,7 +1997,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1974,7 +1997,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1974 | @intCast(u32, array_ty.abiSize(self.target.*)), | 1997 | @intCast(u32, array_ty.abiSize(self.target.*)), |
| 1975 | array_ty.abiAlignment(self.target.*), | 1998 | array_ty.abiAlignment(self.target.*), |
| 1976 | )); | 1999 | )); |
| 1977 | try self.genSetStack(array_ty, off, .rbp, array); | 2000 | try self.genSetStack(array_ty, off, array, .{}); |
| 1978 | break :inner off; | 2001 | break :inner off; |
| 1979 | }, | 2002 | }, |
| 1980 | .stack_offset => |off| { | 2003 | .stack_offset => |off| { |
| ... | @@ -2207,7 +2230,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2207,7 +2230,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2207 | if (abi_size <= 8) { | 2230 | if (abi_size <= 8) { |
| 2208 | const tmp_reg = try self.register_manager.allocReg(null); | 2231 | const tmp_reg = try self.register_manager.allocReg(null); |
| 2209 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); | 2232 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 2210 | return self.genSetStack(elem_ty, off, .rbp, MCValue{ .register = tmp_reg }); | 2233 | return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{}); |
| 2211 | } | 2234 | } |
| 2212 | | 2235 | |
| 2213 | try self.genInlineMemcpy(off, elem_ty, ptr, .{}); | 2236 | try self.genInlineMemcpy(off, elem_ty, ptr, .{}); |
| ... | @@ -2305,7 +2328,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2305,7 +2328,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2305 | try self.store(.{ .register = reg }, value, ptr_ty, value_ty); | 2328 | try self.store(.{ .register = reg }, value, ptr_ty, value_ty); |
| 2306 | }, | 2329 | }, |
| 2307 | .ptr_stack_offset => |off| { | 2330 | .ptr_stack_offset => |off| { |
| 2308 | try self.genSetStack(value_ty, off, .rbp, value); | 2331 | try self.genSetStack(value_ty, off, value, .{}); |
| 2309 | }, | 2332 | }, |
| 2310 | .ptr_embedded_in_code => |off| { | 2333 | .ptr_embedded_in_code => |off| { |
| 2311 | try self.setRegOrMem(value_ty, .{ .embedded_in_code = off }, value); | 2334 | try self.setRegOrMem(value_ty, .{ .embedded_in_code = off }, value); |
| ... | @@ -2779,7 +2802,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC | ... | @@ -2779,7 +2802,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC |
| 2779 | | 2802 | |
| 2780 | switch (src_mcv) { | 2803 | switch (src_mcv) { |
| 2781 | .none => unreachable, | 2804 | .none => unreachable, |
| 2782 | .undef => return self.genSetStack(dst_ty, off, .rbp, .undef), | 2805 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 2783 | .dead, .unreach => unreachable, | 2806 | .dead, .unreach => unreachable, |
| 2784 | .ptr_stack_offset => unreachable, | 2807 | .ptr_stack_offset => unreachable, |
| 2785 | .ptr_embedded_in_code => unreachable, | 2808 | .ptr_embedded_in_code => unreachable, |
| ... | @@ -2922,7 +2945,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! | ... | @@ -2922,7 +2945,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! |
| 2922 | .stack_offset => |off| { | 2945 | .stack_offset => |off| { |
| 2923 | switch (src_mcv) { | 2946 | switch (src_mcv) { |
| 2924 | .none => unreachable, | 2947 | .none => unreachable, |
| 2925 | .undef => return self.genSetStack(dst_ty, off, .rbp, .undef), | 2948 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 2926 | .dead, .unreach => unreachable, | 2949 | .dead, .unreach => unreachable, |
| 2927 | .ptr_stack_offset => unreachable, | 2950 | .ptr_stack_offset => unreachable, |
| 2928 | .ptr_embedded_in_code => unreachable, | 2951 | .ptr_embedded_in_code => unreachable, |
| ... | @@ -2940,7 +2963,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! | ... | @@ -2940,7 +2963,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! |
| 2940 | .data = undefined, | 2963 | .data = undefined, |
| 2941 | }); | 2964 | }); |
| 2942 | // copy dst_reg back out | 2965 | // copy dst_reg back out |
| 2943 | return self.genSetStack(dst_ty, off, .rbp, MCValue{ .register = dst_reg }); | 2966 | return self.genSetStack(dst_ty, off, MCValue{ .register = dst_reg }, .{}); |
| 2944 | }, | 2967 | }, |
| 2945 | .immediate => |imm| { | 2968 | .immediate => |imm| { |
| 2946 | _ = imm; | 2969 | _ = imm; |
| ... | @@ -3279,7 +3302,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3279,7 +3302,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 3279 | }).encode(), | 3302 | }).encode(), |
| 3280 | .data = undefined, | 3303 | .data = undefined, |
| 3281 | }); | 3304 | }); |
| 3282 | try self.genSetStack(ret_ty, 0, reg, operand); | 3305 | try self.genSetStack(ret_ty, 0, operand, .{ |
| | 3306 | .source_stack_base = .rbp, |
| | 3307 | .dest_stack_base = reg, |
| | 3308 | }); |
| 3283 | }, | 3309 | }, |
| 3284 | else => { | 3310 | else => { |
| 3285 | try self.setRegOrMem(ret_ty, self.ret_mcv, operand); | 3311 | try self.setRegOrMem(ret_ty, self.ret_mcv, operand); |
| ... | @@ -4179,7 +4205,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | ... | @@ -4179,7 +4205,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 4179 | .none => return, | 4205 | .none => return, |
| 4180 | .immediate => unreachable, | 4206 | .immediate => unreachable, |
| 4181 | .register => |reg| return self.genSetReg(ty, reg, val), | 4207 | .register => |reg| return self.genSetReg(ty, reg, val), |
| 4182 | .stack_offset => |off| return self.genSetStack(ty, off, .rbp, val), | 4208 | .stack_offset => |off| return self.genSetStack(ty, off, val, .{}), |
| 4183 | .memory => { | 4209 | .memory => { |
| 4184 | return self.fail("TODO implement setRegOrMem for memory", .{}); | 4210 | return self.fail("TODO implement setRegOrMem for memory", .{}); |
| 4185 | }, | 4211 | }, |
| ... | @@ -4200,7 +4226,9 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -4200,7 +4226,9 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 4200 | const reg = try self.copyToTmpRegister(ty, mcv); | 4226 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 4201 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); | 4227 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 4202 | } | 4228 | } |
| 4203 | try self.genInlineMemset(stack_offset, .rsp, ty, .{ .immediate = 0xaa }); | 4229 | try self.genInlineMemset(stack_offset, ty, .{ .immediate = 0xaa }, .{ |
| | 4230 | .dest_stack_base = .rsp, |
| | 4231 | }); |
| 4204 | }, | 4232 | }, |
| 4205 | .compare_flags_unsigned, | 4233 | .compare_flags_unsigned, |
| 4206 | .compare_flags_signed, | 4234 | .compare_flags_signed, |
| ... | @@ -4289,7 +4317,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -4289,7 +4317,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 4289 | } | 4317 | } |
| 4290 | } | 4318 | } |
| 4291 | | 4319 | |
| 4292 | fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv: MCValue) InnerError!void { | 4320 | fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void { |
| 4293 | const abi_size = ty.abiSize(self.target.*); | 4321 | const abi_size = ty.abiSize(self.target.*); |
| 4294 | switch (mcv) { | 4322 | switch (mcv) { |
| 4295 | .dead => unreachable, | 4323 | .dead => unreachable, |
| ... | @@ -4300,20 +4328,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv | ... | @@ -4300,20 +4328,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv |
| 4300 | return; // The already existing value will do just fine. | 4328 | return; // The already existing value will do just fine. |
| 4301 | // TODO Upgrade this to a memset call when we have that available. | 4329 | // TODO Upgrade this to a memset call when we have that available. |
| 4302 | switch (ty.abiSize(self.target.*)) { | 4330 | switch (ty.abiSize(self.target.*)) { |
| 4303 | 1 => return self.genSetStack(ty, stack_offset, base_reg, .{ .immediate = 0xaa }), | 4331 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }, opts), |
| 4304 | 2 => return self.genSetStack(ty, stack_offset, base_reg, .{ .immediate = 0xaaaa }), | 4332 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }, opts), |
| 4305 | 4 => return self.genSetStack(ty, stack_offset, base_reg, .{ .immediate = 0xaaaaaaaa }), | 4333 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }, opts), |
| 4306 | 8 => return self.genSetStack(ty, stack_offset, base_reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }), | 4334 | 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, opts), |
| 4307 | else => return self.genInlineMemset(stack_offset, base_reg, ty, .{ .immediate = 0xaa }), | 4335 | else => return self.genInlineMemset(stack_offset, ty, .{ .immediate = 0xaa }, opts), |
| 4308 | } | 4336 | } |
| 4309 | }, | 4337 | }, |
| 4310 | .compare_flags_unsigned, | 4338 | .compare_flags_unsigned, |
| 4311 | .compare_flags_signed, | 4339 | .compare_flags_signed, |
| 4312 | => { | 4340 | => { |
| 4313 | const reg = try self.copyToTmpRegister(ty, mcv); | 4341 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 4314 | return self.genSetStack(ty, stack_offset, base_reg, .{ .register = reg }); | 4342 | return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); |
| 4315 | }, | 4343 | }, |
| 4316 | .immediate => |x_big| { | 4344 | .immediate => |x_big| { |
| | 4345 | const base_reg = opts.dest_stack_base orelse .rbp; |
| 4317 | switch (abi_size) { | 4346 | switch (abi_size) { |
| 4318 | 1, 2, 4 => { | 4347 | 1, 2, 4 => { |
| 4319 | const payload = try self.addExtra(Mir.ImmPair{ | 4348 | const payload = try self.addExtra(Mir.ImmPair{ |
| ... | @@ -4376,6 +4405,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv | ... | @@ -4376,6 +4405,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv |
| 4376 | return self.fail("stack offset too large", .{}); | 4405 | return self.fail("stack offset too large", .{}); |
| 4377 | } | 4406 | } |
| 4378 | | 4407 | |
| | 4408 | const base_reg = opts.dest_stack_base orelse .rbp; |
| 4379 | const is_power_of_two = (abi_size % 2) == 0; | 4409 | const is_power_of_two = (abi_size % 2) == 0; |
| 4380 | if (!is_power_of_two) { | 4410 | if (!is_power_of_two) { |
| 4381 | self.register_manager.freezeRegs(&.{reg}); | 4411 | self.register_manager.freezeRegs(&.{reg}); |
| ... | @@ -4431,17 +4461,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv | ... | @@ -4431,17 +4461,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv |
| 4431 | => { | 4461 | => { |
| 4432 | if (abi_size <= 8) { | 4462 | if (abi_size <= 8) { |
| 4433 | const reg = try self.copyToTmpRegister(ty, mcv); | 4463 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 4434 | return self.genSetStack(ty, stack_offset, base_reg, MCValue{ .register = reg }); | 4464 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 4435 | } | 4465 | } |
| 4436 | | 4466 | |
| 4437 | try self.genInlineMemcpy(stack_offset, ty, mcv, .{ | 4467 | try self.genInlineMemcpy(stack_offset, ty, mcv, opts); |
| 4438 | .source_stack_base = base_reg, | | |
| 4439 | .dest_stack_base = base_reg, | | |
| 4440 | }); | | |
| 4441 | }, | 4468 | }, |
| 4442 | .ptr_stack_offset => { | 4469 | .ptr_stack_offset => { |
| 4443 | const reg = try self.copyToTmpRegister(ty, mcv); | 4470 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 4444 | return self.genSetStack(ty, stack_offset, base_reg, MCValue{ .register = reg }); | 4471 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 4445 | }, | 4472 | }, |
| 4446 | .stack_offset => |off| { | 4473 | .stack_offset => |off| { |
| 4447 | if (stack_offset == off) { | 4474 | if (stack_offset == off) { |
| ... | @@ -4451,13 +4478,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv | ... | @@ -4451,13 +4478,10 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, base_reg: Register, mcv |
| 4451 | | 4478 | |
| 4452 | if (abi_size <= 8) { | 4479 | if (abi_size <= 8) { |
| 4453 | const reg = try self.copyToTmpRegister(ty, mcv); | 4480 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 4454 | return self.genSetStack(ty, stack_offset, base_reg, MCValue{ .register = reg }); | 4481 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts); |
| 4455 | } | 4482 | } |
| 4456 | | 4483 | |
| 4457 | try self.genInlineMemcpy(stack_offset, ty, mcv, .{ | 4484 | try self.genInlineMemcpy(stack_offset, ty, mcv, opts); |
| 4458 | .source_stack_base = base_reg, | | |
| 4459 | .dest_stack_base = base_reg, | | |
| 4460 | }); | | |
| 4461 | }, | 4485 | }, |
| 4462 | } | 4486 | } |
| 4463 | } | 4487 | } |
| ... | @@ -4627,9 +4651,9 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: | ... | @@ -4627,9 +4651,9 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: |
| 4627 | fn genInlineMemset( | 4651 | fn genInlineMemset( |
| 4628 | self: *Self, | 4652 | self: *Self, |
| 4629 | stack_offset: i32, | 4653 | stack_offset: i32, |
| 4630 | stack_register: Register, | | |
| 4631 | ty: Type, | 4654 | ty: Type, |
| 4632 | value: MCValue, | 4655 | value: MCValue, |
| | 4656 | opts: InlineMemcpyOpts, |
| 4633 | ) InnerError!void { | 4657 | ) InnerError!void { |
| 4634 | try self.register_manager.getReg(.rax, null); | 4658 | try self.register_manager.getReg(.rax, null); |
| 4635 | | 4659 | |
| ... | @@ -4694,7 +4718,7 @@ fn genInlineMemset( | ... | @@ -4694,7 +4718,7 @@ fn genInlineMemset( |
| 4694 | _ = try self.addInst(.{ | 4718 | _ = try self.addInst(.{ |
| 4695 | .tag = .mov_mem_index_imm, | 4719 | .tag = .mov_mem_index_imm, |
| 4696 | .ops = (Mir.Ops{ | 4720 | .ops = (Mir.Ops{ |
| 4697 | .reg1 = stack_register.to64(), | 4721 | .reg1 = opts.dest_stack_base orelse .rbp, |
| 4698 | }).encode(), | 4722 | }).encode(), |
| 4699 | .data = .{ .payload = payload }, | 4723 | .data = .{ .payload = payload }, |
| 4700 | }); | 4724 | }); |
| ... | @@ -5026,8 +5050,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5026,8 +5050,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 5026 | const array_len = array_ty.arrayLenIncludingSentinel(); | 5050 | const array_len = array_ty.arrayLenIncludingSentinel(); |
| 5027 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: { | 5051 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: { |
| 5028 | const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16)); | 5052 | const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16)); |
| 5029 | try self.genSetStack(ptr_ty, stack_offset, .rbp, ptr); | 5053 | try self.genSetStack(ptr_ty, stack_offset, ptr, .{}); |
| 5030 | try self.genSetStack(Type.initTag(.u64), stack_offset - 8, .rbp, .{ .immediate = array_len }); | 5054 | try self.genSetStack(Type.initTag(.u64), stack_offset - 8, .{ .immediate = array_len }, .{}); |
| 5031 | break :blk .{ .stack_offset = stack_offset }; | 5055 | break :blk .{ .stack_offset = stack_offset }; |
| 5032 | }; | 5056 | }; |
| 5033 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 5057 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |