| ... | ... | @@ -864,8 +864,27 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void { |
| 864 | 864 | } |
| 865 | 865 | |
| 866 | 866 | fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 867 | | const stack_offset = try self.allocMemPtr(inst); |
| 868 | | return self.finishAir(inst, .{ .ptr_stack_offset = stack_offset }, .{ .none, .none, .none }); |
| 867 | const result: MCValue = switch (self.ret_mcv) { |
| 868 | .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) }, |
| 869 | .stack_offset => blk: { |
| 870 | // self.ret_mcv is an address to where this function |
| 871 | // should store its result into |
| 872 | const ret_ty = self.fn_type.fnReturnType(); |
| 873 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 874 | .base = .{ .tag = .single_mut_pointer }, |
| 875 | .data = ret_ty, |
| 876 | }; |
| 877 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 878 | |
| 879 | // addr_reg will contain the address of where to store the |
| 880 | // result into |
| 881 | const addr_reg = try self.copyToTmpRegister(ptr_ty, self.ret_mcv); |
| 882 | break :blk .{ .register = addr_reg }; |
| 883 | }, |
| 884 | else => unreachable, // invalid return result |
| 885 | }; |
| 886 | |
| 887 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 869 | 888 | } |
| 870 | 889 | |
| 871 | 890 | fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -1577,9 +1596,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1577 | 1596 | .ptr_embedded_in_code => |off| { |
| 1578 | 1597 | try self.setRegOrMem(elem_ty, dst_mcv, .{ .embedded_in_code = off }); |
| 1579 | 1598 | }, |
| 1580 | | .embedded_in_code => { |
| 1581 | | return self.fail("TODO implement loading from MCValue.embedded_in_code", .{}); |
| 1582 | | }, |
| 1583 | 1599 | .register => |reg| { |
| 1584 | 1600 | self.register_manager.freezeRegs(&.{reg}); |
| 1585 | 1601 | defer self.register_manager.unfreezeRegs(&.{reg}); |
| ... | ... | @@ -1626,6 +1642,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1626 | 1642 | } |
| 1627 | 1643 | }, |
| 1628 | 1644 | .memory, |
| 1645 | .embedded_in_code, |
| 1629 | 1646 | .stack_offset, |
| 1630 | 1647 | .stack_argument_offset, |
| 1631 | 1648 | => { |
| ... | ... | @@ -1684,9 +1701,6 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1684 | 1701 | .ptr_embedded_in_code => |off| { |
| 1685 | 1702 | try self.setRegOrMem(value_ty, .{ .embedded_in_code = off }, value); |
| 1686 | 1703 | }, |
| 1687 | | .embedded_in_code => { |
| 1688 | | return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); |
| 1689 | | }, |
| 1690 | 1704 | .register => |addr_reg| { |
| 1691 | 1705 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 1692 | 1706 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| ... | ... | @@ -1719,7 +1733,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1719 | 1733 | switch (value) { |
| 1720 | 1734 | .stack_offset => |off| { |
| 1721 | 1735 | // sub src_reg, fp, #off |
| 1722 | | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = off }); |
| 1736 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 1723 | 1737 | }, |
| 1724 | 1738 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 1725 | 1739 | else => return self.fail("TODO store {} to register", .{value}), |
| ... | ... | @@ -1735,6 +1749,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1735 | 1749 | } |
| 1736 | 1750 | }, |
| 1737 | 1751 | .memory, |
| 1752 | .embedded_in_code, |
| 1738 | 1753 | .stack_offset, |
| 1739 | 1754 | .stack_argument_offset, |
| 1740 | 1755 | => { |
| ... | ... | @@ -2656,13 +2671,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 2656 | 2671 | return bt.finishAir(result); |
| 2657 | 2672 | } |
| 2658 | 2673 | |
| 2659 | | fn ret(self: *Self, mcv: MCValue) !void { |
| 2674 | fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 2675 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2676 | const operand = try self.resolveInst(un_op); |
| 2660 | 2677 | const ret_ty = self.fn_type.fnReturnType(); |
| 2678 | |
| 2661 | 2679 | switch (self.ret_mcv) { |
| 2662 | 2680 | .none => {}, |
| 2663 | 2681 | .register => |reg| { |
| 2664 | 2682 | // Return result by value |
| 2665 | | try self.genSetReg(ret_ty, reg, mcv); |
| 2683 | try self.genSetReg(ret_ty, reg, operand); |
| 2666 | 2684 | }, |
| 2667 | 2685 | .stack_offset => { |
| 2668 | 2686 | // Return result by reference |
| ... | ... | @@ -2674,28 +2692,66 @@ fn ret(self: *Self, mcv: MCValue) !void { |
| 2674 | 2692 | .data = ret_ty, |
| 2675 | 2693 | }; |
| 2676 | 2694 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 2677 | | try self.store(self.ret_mcv, mcv, ptr_ty, ret_ty); |
| 2695 | try self.store(self.ret_mcv, operand, ptr_ty, ret_ty); |
| 2678 | 2696 | }, |
| 2679 | 2697 | else => unreachable, // invalid return result |
| 2680 | 2698 | } |
| 2681 | 2699 | |
| 2682 | 2700 | // Just add space for an instruction, patch this later |
| 2683 | 2701 | try self.exitlude_jump_relocs.append(self.gpa, try self.addNop()); |
| 2684 | | } |
| 2685 | 2702 | |
| 2686 | | fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 2687 | | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2688 | | const operand = try self.resolveInst(un_op); |
| 2689 | | try self.ret(operand); |
| 2690 | 2703 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); |
| 2691 | 2704 | } |
| 2692 | 2705 | |
| 2693 | 2706 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2694 | 2707 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 2695 | 2708 | const ptr = try self.resolveInst(un_op); |
| 2696 | | _ = ptr; |
| 2697 | | return self.fail("TODO implement airRetLoad for {}", .{self.target.cpu.arch}); |
| 2698 | | //return self.finishAir(inst, .dead, .{ un_op, .none, .none }); |
| 2709 | const ptr_ty = self.air.typeOf(un_op); |
| 2710 | const ret_ty = self.fn_type.fnReturnType(); |
| 2711 | |
| 2712 | switch (self.ret_mcv) { |
| 2713 | .none => {}, |
| 2714 | .register => { |
| 2715 | // Return result by value |
| 2716 | try self.load(self.ret_mcv, ptr, ptr_ty); |
| 2717 | }, |
| 2718 | .stack_offset => { |
| 2719 | // Return result by reference |
| 2720 | // |
| 2721 | // self.ret_mcv is an address to where this function |
| 2722 | // should store its result into |
| 2723 | // |
| 2724 | // If the operand is a ret_ptr instruction, we are done |
| 2725 | // here. Else we need to load the result from the location |
| 2726 | // pointed to by the operand and store it to the result |
| 2727 | // location. |
| 2728 | const op_inst = Air.refToIndex(un_op).?; |
| 2729 | if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) { |
| 2730 | const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| 2731 | const abi_align = ret_ty.abiAlignment(self.target.*); |
| 2732 | |
| 2733 | // This is essentially allocMem without the |
| 2734 | // instruction tracking |
| 2735 | if (abi_align > self.stack_align) |
| 2736 | self.stack_align = abi_align; |
| 2737 | // TODO find a free slot instead of always appending |
| 2738 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align); |
| 2739 | self.next_stack_offset = offset + abi_size; |
| 2740 | if (self.next_stack_offset > self.max_end_stack) |
| 2741 | self.max_end_stack = self.next_stack_offset; |
| 2742 | |
| 2743 | const tmp_mcv = MCValue{ .stack_offset = offset }; |
| 2744 | try self.load(tmp_mcv, ptr, ptr_ty); |
| 2745 | try self.store(self.ret_mcv, tmp_mcv, ptr_ty, ret_ty); |
| 2746 | } |
| 2747 | }, |
| 2748 | else => unreachable, // invalid return result |
| 2749 | } |
| 2750 | |
| 2751 | // Just add space for an instruction, patch this later |
| 2752 | try self.exitlude_jump_relocs.append(self.gpa, try self.addNop()); |
| 2753 | |
| 2754 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); |
| 2699 | 2755 | } |
| 2700 | 2756 | |
| 2701 | 2757 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |