| ... | ... | @@ -810,8 +810,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 810 | 810 | if (abi_align > self.stack_align) |
| 811 | 811 | self.stack_align = abi_align; |
| 812 | 812 | // TODO find a free slot instead of always appending |
| 813 | | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align); |
| 814 | | self.next_stack_offset = offset + abi_size; |
| 813 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset + abi_size, abi_align); |
| 814 | self.next_stack_offset = offset; |
| 815 | 815 | if (self.next_stack_offset > self.max_end_stack) |
| 816 | 816 | self.max_end_stack = self.next_stack_offset; |
| 817 | 817 | try self.stack.putNoClobber(self.gpa, offset, .{ |
| ... | ... | @@ -823,7 +823,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 823 | 823 | |
| 824 | 824 | /// Use a pointer instruction as the basis for allocating stack memory. |
| 825 | 825 | fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 826 | | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 826 | const ptr_ty = self.air.typeOfIndex(inst); |
| 827 | const elem_ty = ptr_ty.elemType(); |
| 827 | 828 | |
| 828 | 829 | if (!elem_ty.hasRuntimeBits()) { |
| 829 | 830 | return self.allocMem(inst, 8, 8); |
| ... | ... | @@ -833,7 +834,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 833 | 834 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty}); |
| 834 | 835 | }; |
| 835 | 836 | // TODO swap this for inst.ty.ptrAlign |
| 836 | | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 837 | const abi_align = ptr_ty.ptrAlignment(self.target.*); |
| 837 | 838 | return self.allocMem(inst, abi_size, abi_align); |
| 838 | 839 | } |
| 839 | 840 | |
| ... | ... | @@ -1148,8 +1149,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1148 | 1149 | const len_ty = self.air.typeOf(bin_op.rhs); |
| 1149 | 1150 | |
| 1150 | 1151 | const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16)); |
| 1151 | | try self.genSetStack(ptr_ty, stack_offset + 8, ptr); |
| 1152 | | try self.genSetStack(len_ty, stack_offset, len); |
| 1152 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 1153 | try self.genSetStack(len_ty, stack_offset - 8, len); |
| 1153 | 1154 | const result = MCValue{ .stack_offset = stack_offset }; |
| 1154 | 1155 | |
| 1155 | 1156 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | ... | @@ -1455,7 +1456,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1455 | 1456 | const dst_mcv: MCValue = blk: { |
| 1456 | 1457 | switch (operand) { |
| 1457 | 1458 | .stack_offset => |off| { |
| 1458 | | break :blk MCValue{ .stack_offset = off + 8 }; |
| 1459 | break :blk MCValue{ .stack_offset = off }; |
| 1459 | 1460 | }, |
| 1460 | 1461 | else => return self.fail("TODO implement slice_ptr for {}", .{operand}), |
| 1461 | 1462 | } |
| ... | ... | @@ -1472,7 +1473,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1472 | 1473 | const dst_mcv: MCValue = blk: { |
| 1473 | 1474 | switch (operand) { |
| 1474 | 1475 | .stack_offset => |off| { |
| 1475 | | break :blk MCValue{ .stack_offset = off }; |
| 1476 | break :blk MCValue{ .stack_offset = off - 8 }; |
| 1476 | 1477 | }, |
| 1477 | 1478 | else => return self.fail("TODO implement slice_len for {}", .{operand}), |
| 1478 | 1479 | } |
| ... | ... | @@ -1540,7 +1541,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1540 | 1541 | .reg2 = .rbp, |
| 1541 | 1542 | .flags = 0b01, |
| 1542 | 1543 | }).encode(), |
| 1543 | | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) }, |
| 1544 | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) }, |
| 1544 | 1545 | }); |
| 1545 | 1546 | }, |
| 1546 | 1547 | else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}), |
| ... | ... | @@ -1571,7 +1572,6 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1571 | 1572 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1572 | 1573 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1573 | 1574 | const array_ty = self.air.typeOf(bin_op.lhs); |
| 1574 | | const array_abi_size = array_ty.abiSize(self.target.*); |
| 1575 | 1575 | const array = try self.resolveInst(bin_op.lhs); |
| 1576 | 1576 | array.freezeIfRegister(&self.register_manager); |
| 1577 | 1577 | defer array.unfreezeIfRegister(&self.register_manager); |
| ... | ... | @@ -1597,7 +1597,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1597 | 1597 | .reg1 = addr_reg.to64(), |
| 1598 | 1598 | .reg2 = .rbp, |
| 1599 | 1599 | }).encode(), |
| 1600 | | .data = .{ .imm = @bitCast(u32, -(off + @intCast(i32, array_abi_size))) }, |
| 1600 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 1601 | 1601 | }); |
| 1602 | 1602 | }, |
| 1603 | 1603 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| ... | ... | @@ -1806,7 +1806,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1806 | 1806 | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 1807 | 1807 | |
| 1808 | 1808 | return self.genInlineMemcpy( |
| 1809 | | -(off + @intCast(i32, abi_size)), |
| 1809 | -off, |
| 1810 | 1810 | .rbp, |
| 1811 | 1811 | registerAlias(addr_reg, @divExact(reg.size(), 8)), |
| 1812 | 1812 | count_reg.to64(), |
| ... | ... | @@ -2093,10 +2093,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2093 | 2093 | const mcv = try self.resolveInst(operand); |
| 2094 | 2094 | const ptr_ty = self.air.typeOf(operand); |
| 2095 | 2095 | const struct_ty = ptr_ty.childType(); |
| 2096 | | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); |
| 2097 | 2096 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 2098 | | const struct_field_ty = struct_ty.structFieldType(index); |
| 2099 | | const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); |
| 2100 | 2097 | |
| 2101 | 2098 | const dst_mcv: MCValue = result: { |
| 2102 | 2099 | switch (mcv) { |
| ... | ... | @@ -2112,8 +2109,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2112 | 2109 | break :result dst_mcv; |
| 2113 | 2110 | }, |
| 2114 | 2111 | .ptr_stack_offset => |off| { |
| 2115 | | const offset_to_field = struct_size - struct_field_offset - struct_field_size; |
| 2116 | | const ptr_stack_offset = off + @intCast(i32, offset_to_field); |
| 2112 | const ptr_stack_offset = off - @intCast(i32, struct_field_offset); |
| 2117 | 2113 | break :result MCValue{ .ptr_stack_offset = ptr_stack_offset }; |
| 2118 | 2114 | }, |
| 2119 | 2115 | .register => |reg| { |
| ... | ... | @@ -2153,15 +2149,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2153 | 2149 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2154 | 2150 | const mcv = try self.resolveInst(operand); |
| 2155 | 2151 | const struct_ty = self.air.typeOf(operand); |
| 2156 | | const struct_size = struct_ty.abiSize(self.target.*); |
| 2157 | 2152 | const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*); |
| 2158 | 2153 | const struct_field_ty = struct_ty.structFieldType(index); |
| 2159 | | const struct_field_size = struct_field_ty.abiSize(self.target.*); |
| 2160 | 2154 | |
| 2161 | 2155 | switch (mcv) { |
| 2162 | 2156 | .stack_offset => |off| { |
| 2163 | | const offset_to_field = struct_size - struct_field_offset - struct_field_size; |
| 2164 | | const stack_offset = off + @intCast(i32, offset_to_field); |
| 2157 | const stack_offset = off - @intCast(i32, struct_field_offset); |
| 2165 | 2158 | break :result MCValue{ .stack_offset = stack_offset }; |
| 2166 | 2159 | }, |
| 2167 | 2160 | .register => |reg| { |
| ... | ... | @@ -2369,7 +2362,6 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC |
| 2369 | 2362 | if (off > math.maxInt(i32)) { |
| 2370 | 2363 | return self.fail("stack offset too large", .{}); |
| 2371 | 2364 | } |
| 2372 | | const adj_off = off + @intCast(i32, abi_size); |
| 2373 | 2365 | _ = try self.addInst(.{ |
| 2374 | 2366 | .tag = mir_tag, |
| 2375 | 2367 | .ops = (Mir.Ops{ |
| ... | ... | @@ -2377,7 +2369,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC |
| 2377 | 2369 | .reg2 = .rbp, |
| 2378 | 2370 | .flags = 0b01, |
| 2379 | 2371 | }).encode(), |
| 2380 | | .data = .{ .imm = @bitCast(u32, -adj_off) }, |
| 2372 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 2381 | 2373 | }); |
| 2382 | 2374 | }, |
| 2383 | 2375 | .compare_flags_unsigned => { |
| ... | ... | @@ -2395,7 +2387,6 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC |
| 2395 | 2387 | if (abi_size > 8) { |
| 2396 | 2388 | return self.fail("TODO implement ADD/SUB/CMP for stack dst with large ABI", .{}); |
| 2397 | 2389 | } |
| 2398 | | const adj_off = off + @intCast(i32, abi_size); |
| 2399 | 2390 | |
| 2400 | 2391 | switch (src_mcv) { |
| 2401 | 2392 | .none => unreachable, |
| ... | ... | @@ -2411,7 +2402,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC |
| 2411 | 2402 | .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), |
| 2412 | 2403 | .flags = 0b10, |
| 2413 | 2404 | }).encode(), |
| 2414 | | .data = .{ .imm = @bitCast(u32, -adj_off) }, |
| 2405 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 2415 | 2406 | }); |
| 2416 | 2407 | }, |
| 2417 | 2408 | .immediate => |imm| { |
| ... | ... | @@ -2432,7 +2423,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC |
| 2432 | 2423 | else => unreachable, |
| 2433 | 2424 | }; |
| 2434 | 2425 | const payload = try self.addExtra(Mir.ImmPair{ |
| 2435 | | .dest_off = @bitCast(u32, -adj_off), |
| 2426 | .dest_off = @bitCast(u32, -off), |
| 2436 | 2427 | .operand = @truncate(u32, imm), |
| 2437 | 2428 | }); |
| 2438 | 2429 | _ = try self.addInst(.{ |
| ... | ... | @@ -2583,9 +2574,16 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 2583 | 2574 | self.arg_index += 1; |
| 2584 | 2575 | |
| 2585 | 2576 | const mcv = self.args[arg_index]; |
| 2577 | const max_stack = loop: for (self.args) |arg| { |
| 2578 | switch (arg) { |
| 2579 | .stack_offset => |last| break :loop last, |
| 2580 | else => {}, |
| 2581 | } |
| 2582 | } else 0; |
| 2586 | 2583 | const payload = try self.addExtra(Mir.ArgDbgInfo{ |
| 2587 | 2584 | .air_inst = inst, |
| 2588 | 2585 | .arg_index = arg_index, |
| 2586 | .max_stack = @intCast(u32, max_stack), |
| 2589 | 2587 | }); |
| 2590 | 2588 | _ = try self.addInst(.{ |
| 2591 | 2589 | .tag = .arg_dbg_info, |
| ... | ... | @@ -2601,11 +2599,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 2601 | 2599 | self.register_manager.getRegAssumeFree(reg.to64(), inst); |
| 2602 | 2600 | break :blk mcv; |
| 2603 | 2601 | }, |
| 2604 | | .stack_offset => { |
| 2605 | | const ty = self.air.typeOfIndex(inst); |
| 2606 | | const abi_size = ty.abiSize(self.target.*); |
| 2607 | | const off = @intCast(i32, (arg_index + 1) * abi_size) + 16; |
| 2608 | | break :blk MCValue{ .stack_offset = -off }; |
| 2602 | .stack_offset => |off| { |
| 2603 | const offset = max_stack - off + 16; |
| 2604 | break :blk MCValue{ .stack_offset = -offset }; |
| 2609 | 2605 | }, |
| 2610 | 2606 | else => return self.fail("TODO implement arg for {}", .{mcv}), |
| 2611 | 2607 | } |
| ... | ... | @@ -2648,7 +2644,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2648 | 2644 | var info = try self.resolveCallingConventionValues(fn_ty); |
| 2649 | 2645 | defer info.deinit(self); |
| 2650 | 2646 | |
| 2651 | | var stack_adjustment: u32 = 0; |
| 2647 | var stack_adjustment: ?u32 = null; |
| 2652 | 2648 | for (args) |arg, arg_i| { |
| 2653 | 2649 | const mc_arg = info.args[arg_i]; |
| 2654 | 2650 | const arg_ty = self.air.typeOf(arg); |
| ... | ... | @@ -2662,9 +2658,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2662 | 2658 | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 2663 | 2659 | }, |
| 2664 | 2660 | .stack_offset => |off| { |
| 2665 | | const abi_size = @intCast(u32, arg_ty.abiSize(self.target.*)); |
| 2666 | 2661 | try self.genSetStackArg(arg_ty, off, arg_mcv); |
| 2667 | | stack_adjustment += abi_size; |
| 2662 | if (stack_adjustment == null) { |
| 2663 | stack_adjustment = @intCast(u32, off); |
| 2664 | } |
| 2668 | 2665 | }, |
| 2669 | 2666 | .ptr_stack_offset => { |
| 2670 | 2667 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| ... | ... | @@ -2685,14 +2682,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2685 | 2682 | } |
| 2686 | 2683 | } |
| 2687 | 2684 | |
| 2688 | | if (stack_adjustment > 0) { |
| 2685 | if (stack_adjustment) |off| { |
| 2689 | 2686 | // Adjust the stack |
| 2690 | 2687 | _ = try self.addInst(.{ |
| 2691 | 2688 | .tag = .sub, |
| 2692 | 2689 | .ops = (Mir.Ops{ |
| 2693 | 2690 | .reg1 = .rsp, |
| 2694 | 2691 | }).encode(), |
| 2695 | | .data = .{ .imm = stack_adjustment }, |
| 2692 | .data = .{ .imm = off }, |
| 2696 | 2693 | }); |
| 2697 | 2694 | } |
| 2698 | 2695 | |
| ... | ... | @@ -2820,14 +2817,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2820 | 2817 | } |
| 2821 | 2818 | } else unreachable; |
| 2822 | 2819 | |
| 2823 | | if (stack_adjustment > 0) { |
| 2820 | if (stack_adjustment) |off| { |
| 2824 | 2821 | // Readjust the stack |
| 2825 | 2822 | _ = try self.addInst(.{ |
| 2826 | 2823 | .tag = .add, |
| 2827 | 2824 | .ops = (Mir.Ops{ |
| 2828 | 2825 | .reg1 = .rsp, |
| 2829 | 2826 | }).encode(), |
| 2830 | | .data = .{ .imm = stack_adjustment }, |
| 2827 | .data = .{ .imm = off }, |
| 2831 | 2828 | }); |
| 2832 | 2829 | } |
| 2833 | 2830 | |
| ... | ... | @@ -3583,14 +3580,13 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3583 | 3580 | return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); |
| 3584 | 3581 | }, |
| 3585 | 3582 | .immediate => |imm| { |
| 3586 | | const off = stack_offset + @intCast(i32, abi_size); |
| 3587 | 3583 | switch (abi_size) { |
| 3588 | 3584 | 1, 2, 4 => { |
| 3589 | 3585 | // We have a positive stack offset value but we want a twos complement negative |
| 3590 | 3586 | // offset from rbp, which is at the top of the stack frame. |
| 3591 | 3587 | // mov [rbp+offset], immediate |
| 3592 | 3588 | const payload = try self.addExtra(Mir.ImmPair{ |
| 3593 | | .dest_off = @bitCast(u32, -off), |
| 3589 | .dest_off = @bitCast(u32, -stack_offset), |
| 3594 | 3590 | .operand = @truncate(u32, imm), |
| 3595 | 3591 | }); |
| 3596 | 3592 | _ = try self.addInst(.{ |
| ... | ... | @@ -3680,7 +3676,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3680 | 3676 | // TODO allow for abi_size to be u64 |
| 3681 | 3677 | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3682 | 3678 | try self.genInlineMemcpy( |
| 3683 | | -(stack_offset + @intCast(i32, abi_size)), |
| 3679 | -stack_offset, |
| 3684 | 3680 | .rsp, |
| 3685 | 3681 | addr_reg.to64(), |
| 3686 | 3682 | count_reg.to64(), |
| ... | ... | @@ -3695,14 +3691,14 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3695 | 3691 | .reg2 = registerAlias(reg, @intCast(u32, abi_size)), |
| 3696 | 3692 | .flags = 0b10, |
| 3697 | 3693 | }).encode(), |
| 3698 | | .data = .{ .imm = @bitCast(u32, -(stack_offset + @intCast(i32, abi_size))) }, |
| 3694 | .data = .{ .imm = @bitCast(u32, -stack_offset) }, |
| 3699 | 3695 | }); |
| 3700 | 3696 | }, |
| 3701 | 3697 | .ptr_stack_offset => { |
| 3702 | 3698 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3703 | 3699 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 3704 | 3700 | }, |
| 3705 | | .stack_offset => |unadjusted_off| { |
| 3701 | .stack_offset => |off| { |
| 3706 | 3702 | if (abi_size <= 8) { |
| 3707 | 3703 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3708 | 3704 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| ... | ... | @@ -3725,13 +3721,13 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3725 | 3721 | .reg1 = addr_reg.to64(), |
| 3726 | 3722 | .reg2 = .rbp, |
| 3727 | 3723 | }).encode(), |
| 3728 | | .data = .{ .imm = @bitCast(u32, -(unadjusted_off + @intCast(i32, abi_size))) }, |
| 3724 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 3729 | 3725 | }); |
| 3730 | 3726 | |
| 3731 | 3727 | // TODO allow for abi_size to be u64 |
| 3732 | 3728 | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3733 | 3729 | try self.genInlineMemcpy( |
| 3734 | | -(stack_offset + @intCast(i32, abi_size)), |
| 3730 | -stack_offset, |
| 3735 | 3731 | .rsp, |
| 3736 | 3732 | addr_reg.to64(), |
| 3737 | 3733 | count_reg.to64(), |
| ... | ... | @@ -3767,17 +3763,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3767 | 3763 | return self.genSetStack(ty, stack_offset, .{ .register = reg }); |
| 3768 | 3764 | }, |
| 3769 | 3765 | .immediate => |x_big| { |
| 3770 | | const adj_off = stack_offset + @intCast(i32, abi_size); |
| 3771 | | if (adj_off > 128) { |
| 3766 | if (stack_offset > 128) { |
| 3772 | 3767 | return self.fail("TODO implement set stack variable with large stack offset", .{}); |
| 3773 | 3768 | } |
| 3774 | 3769 | switch (abi_size) { |
| 3775 | 3770 | 1, 2, 4 => { |
| 3776 | | // We have a positive stack offset value but we want a twos complement negative |
| 3777 | | // offset from rbp, which is at the top of the stack frame. |
| 3778 | | // mov [rbp+offset], immediate |
| 3779 | 3771 | const payload = try self.addExtra(Mir.ImmPair{ |
| 3780 | | .dest_off = @bitCast(u32, -adj_off), |
| 3772 | .dest_off = @bitCast(u32, -stack_offset), |
| 3781 | 3773 | .operand = @truncate(u32, x_big), |
| 3782 | 3774 | }); |
| 3783 | 3775 | _ = try self.addInst(.{ |
| ... | ... | @@ -3795,15 +3787,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3795 | 3787 | }); |
| 3796 | 3788 | }, |
| 3797 | 3789 | 8 => { |
| 3798 | | // We have a positive stack offset value but we want a twos complement negative |
| 3799 | | // offset from rbp, which is at the top of the stack frame. |
| 3800 | | const negative_offset = -adj_off; |
| 3801 | | |
| 3802 | 3790 | // 64 bit write to memory would take two mov's anyways so we |
| 3803 | 3791 | // insted just use two 32 bit writes to avoid register allocation |
| 3804 | 3792 | { |
| 3805 | 3793 | const payload = try self.addExtra(Mir.ImmPair{ |
| 3806 | | .dest_off = @bitCast(u32, negative_offset + 4), |
| 3794 | .dest_off = @bitCast(u32, -stack_offset + 4), |
| 3807 | 3795 | .operand = @truncate(u32, x_big >> 32), |
| 3808 | 3796 | }); |
| 3809 | 3797 | _ = try self.addInst(.{ |
| ... | ... | @@ -3817,7 +3805,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3817 | 3805 | } |
| 3818 | 3806 | { |
| 3819 | 3807 | const payload = try self.addExtra(Mir.ImmPair{ |
| 3820 | | .dest_off = @bitCast(u32, negative_offset), |
| 3808 | .dest_off = @bitCast(u32, -stack_offset), |
| 3821 | 3809 | .operand = @truncate(u32, x_big), |
| 3822 | 3810 | }); |
| 3823 | 3811 | _ = try self.addInst(.{ |
| ... | ... | @@ -3839,7 +3827,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3839 | 3827 | if (stack_offset > math.maxInt(i32)) { |
| 3840 | 3828 | return self.fail("stack offset too large", .{}); |
| 3841 | 3829 | } |
| 3842 | | const adj_off = stack_offset + @intCast(i32, abi_size); |
| 3843 | 3830 | _ = try self.addInst(.{ |
| 3844 | 3831 | .tag = .mov, |
| 3845 | 3832 | .ops = (Mir.Ops{ |
| ... | ... | @@ -3847,7 +3834,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3847 | 3834 | .reg2 = registerAlias(reg, @intCast(u32, abi_size)), |
| 3848 | 3835 | .flags = 0b10, |
| 3849 | 3836 | }).encode(), |
| 3850 | | .data = .{ .imm = @bitCast(u32, -adj_off) }, |
| 3837 | .data = .{ .imm = @bitCast(u32, -stack_offset) }, |
| 3851 | 3838 | }); |
| 3852 | 3839 | }, |
| 3853 | 3840 | .memory, |
| ... | ... | @@ -3913,7 +3900,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3913 | 3900 | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3914 | 3901 | |
| 3915 | 3902 | return self.genInlineMemcpy( |
| 3916 | | -(stack_offset + @intCast(i32, abi_size)), |
| 3903 | -stack_offset, |
| 3917 | 3904 | .rbp, |
| 3918 | 3905 | addr_reg.to64(), |
| 3919 | 3906 | count_reg.to64(), |
| ... | ... | @@ -3952,14 +3939,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro |
| 3952 | 3939 | .reg1 = addr_reg.to64(), |
| 3953 | 3940 | .reg2 = .rbp, |
| 3954 | 3941 | }).encode(), |
| 3955 | | .data = .{ .imm = @bitCast(u32, -(off + @intCast(i32, abi_size))) }, |
| 3942 | .data = .{ .imm = @bitCast(u32, -off) }, |
| 3956 | 3943 | }); |
| 3957 | 3944 | |
| 3958 | 3945 | // TODO allow for abi_size to be u64 |
| 3959 | 3946 | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3960 | 3947 | |
| 3961 | 3948 | return self.genInlineMemcpy( |
| 3962 | | -(stack_offset + @intCast(i32, abi_size)), |
| 3949 | -stack_offset, |
| 3963 | 3950 | .rbp, |
| 3964 | 3951 | addr_reg.to64(), |
| 3965 | 3952 | count_reg.to64(), |
| ... | ... | @@ -4073,11 +4060,10 @@ fn genInlineMemcpy( |
| 4073 | 4060 | fn genInlineMemset(self: *Self, ty: Type, stack_offset: i32, value: MCValue) InnerError!void { |
| 4074 | 4061 | try self.register_manager.getReg(.rax, null); |
| 4075 | 4062 | const abi_size = ty.abiSize(self.target.*); |
| 4076 | | const adj_off = stack_offset + @intCast(i32, abi_size); |
| 4077 | | if (adj_off > 128) { |
| 4063 | if (stack_offset > 128) { |
| 4078 | 4064 | return self.fail("TODO inline memset with large stack offset", .{}); |
| 4079 | 4065 | } |
| 4080 | | const negative_offset = @bitCast(u32, -adj_off); |
| 4066 | const negative_offset = @bitCast(u32, -stack_offset); |
| 4081 | 4067 | |
| 4082 | 4068 | // We are actually counting `abi_size` bytes; however, we reuse the index register |
| 4083 | 4069 | // as both the counter and offset scaler, hence we need to subtract one from `abi_size` |
| ... | ... | @@ -4165,10 +4151,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4165 | 4151 | const abi_size = ty.abiSize(self.target.*); |
| 4166 | 4152 | switch (mcv) { |
| 4167 | 4153 | .dead => unreachable, |
| 4168 | | .ptr_stack_offset => |unadjusted_off| { |
| 4169 | | const elem_ty = ty.childType(); |
| 4170 | | const elem_abi_size = elem_ty.abiSize(self.target.*); |
| 4171 | | const off = unadjusted_off + @intCast(i32, elem_abi_size); |
| 4154 | .ptr_stack_offset => |off| { |
| 4172 | 4155 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 4173 | 4156 | return self.fail("stack offset too large", .{}); |
| 4174 | 4157 | } |
| ... | ... | @@ -4391,8 +4374,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4391 | 4374 | } |
| 4392 | 4375 | } |
| 4393 | 4376 | }, |
| 4394 | | .stack_offset => |unadjusted_off| { |
| 4395 | | const off = unadjusted_off + @intCast(i32, abi_size); |
| 4377 | .stack_offset => |off| { |
| 4396 | 4378 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 4397 | 4379 | return self.fail("stack offset too large", .{}); |
| 4398 | 4380 | } |
| ... | ... | @@ -4469,8 +4451,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 4469 | 4451 | const array_len = array_ty.arrayLenIncludingSentinel(); |
| 4470 | 4452 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: { |
| 4471 | 4453 | const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16)); |
| 4472 | | try self.genSetStack(ptr_ty, stack_offset + 8, ptr); |
| 4473 | | try self.genSetStack(Type.initTag(.u64), stack_offset, .{ .immediate = array_len }); |
| 4454 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 4455 | try self.genSetStack(Type.initTag(.u64), stack_offset - 8, .{ .immediate = array_len }); |
| 4474 | 4456 | break :blk .{ .stack_offset = stack_offset }; |
| 4475 | 4457 | }; |
| 4476 | 4458 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -4883,7 +4865,6 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4883 | 4865 | var next_stack_offset: u32 = 0; |
| 4884 | 4866 | var count: usize = param_types.len; |
| 4885 | 4867 | while (count > 0) : (count -= 1) { |
| 4886 | | // for (param_types) |ty, i| { |
| 4887 | 4868 | const i = count - 1; |
| 4888 | 4869 | const ty = param_types[i]; |
| 4889 | 4870 | if (!ty.hasRuntimeBits()) { |
| ... | ... | @@ -4892,6 +4873,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4892 | 4873 | continue; |
| 4893 | 4874 | } |
| 4894 | 4875 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4876 | const param_align = @intCast(u32, ty.abiAlignment(self.target.*)); |
| 4895 | 4877 | if (by_reg.get(i)) |int_reg| { |
| 4896 | 4878 | const aliased_reg = registerAlias(c_abi_int_param_regs[int_reg], param_size); |
| 4897 | 4879 | result.args[i] = .{ .register = aliased_reg }; |
| ... | ... | @@ -4902,8 +4884,9 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4902 | 4884 | // such as ptr and len of slices as separate registers. |
| 4903 | 4885 | // TODO: also we need to honor the C ABI for relevant types rather than passing on |
| 4904 | 4886 | // the stack here. |
| 4905 | | result.args[i] = .{ .stack_offset = @intCast(i32, next_stack_offset) }; |
| 4906 | | next_stack_offset += param_size; |
| 4887 | const offset = mem.alignForwardGeneric(u32, next_stack_offset + param_size, param_align); |
| 4888 | result.args[i] = .{ .stack_offset = @intCast(i32, offset) }; |
| 4889 | next_stack_offset = offset; |
| 4907 | 4890 | } |
| 4908 | 4891 | } |
| 4909 | 4892 | |