| ... | @@ -128,12 +128,8 @@ pub const MCValue = union(enum) { | ... | @@ -128,12 +128,8 @@ pub const MCValue = union(enum) { |
| 128 | immediate: u64, | 128 | immediate: u64, |
| 129 | /// The value is in a GP register. | 129 | /// The value is in a GP register. |
| 130 | register: Register, | 130 | register: Register, |
| 131 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register, | 131 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register. |
| 132 | /// and the operation is an unsigned operation. | 132 | register_overflow: struct { reg: Register, eflags: Condition }, |
| 133 | register_overflow_unsigned: Register, | | |
| 134 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register, | | |
| 135 | /// and the operation is a signed operation. | | |
| 136 | register_overflow_signed: Register, | | |
| 137 | /// The value is in memory at a hard-coded address. | 133 | /// The value is in memory at a hard-coded address. |
| 138 | /// If the type is a pointer, it means the pointer address is at this memory location. | 134 | /// If the type is a pointer, it means the pointer address is at this memory location. |
| 139 | memory: u64, | 135 | memory: u64, |
| ... | @@ -183,8 +179,7 @@ pub const MCValue = union(enum) { | ... | @@ -183,8 +179,7 @@ pub const MCValue = union(enum) { |
| 183 | .eflags, | 179 | .eflags, |
| 184 | .ptr_stack_offset, | 180 | .ptr_stack_offset, |
| 185 | .undef, | 181 | .undef, |
| 186 | .register_overflow_unsigned, | 182 | .register_overflow, |
| 187 | .register_overflow_signed, | | |
| 188 | => false, | 183 | => false, |
| 189 | | 184 | |
| 190 | .register, | 185 | .register, |
| ... | @@ -774,8 +769,8 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { | ... | @@ -774,8 +769,8 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 774 | .register => |reg| { | 769 | .register => |reg| { |
| 775 | self.register_manager.freeReg(reg.to64()); | 770 | self.register_manager.freeReg(reg.to64()); |
| 776 | }, | 771 | }, |
| 777 | .register_overflow_signed, .register_overflow_unsigned => |reg| { | 772 | .register_overflow => |ro| { |
| 778 | self.register_manager.freeReg(reg.to64()); | 773 | self.register_manager.freeReg(ro.reg.to64()); |
| 779 | self.eflags_inst = null; | 774 | self.eflags_inst = null; |
| 780 | }, | 775 | }, |
| 781 | .eflags => { | 776 | .eflags => { |
| ... | @@ -809,20 +804,22 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live | ... | @@ -809,20 +804,22 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live |
| 809 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 804 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 810 | branch.inst_table.putAssumeCapacityNoClobber(inst, result); | 805 | branch.inst_table.putAssumeCapacityNoClobber(inst, result); |
| 811 | | 806 | |
| | 807 | // In some cases (such as bitcast), an operand |
| | 808 | // may be the same MCValue as the result. If |
| | 809 | // that operand died and was a register, it |
| | 810 | // was freed by processDeath. We have to |
| | 811 | // "re-allocate" the register. |
| 812 | switch (result) { | 812 | switch (result) { |
| 813 | .register, | 813 | .register => |reg| { |
| 814 | .register_overflow_signed, | | |
| 815 | .register_overflow_unsigned, | | |
| 816 | => |reg| { | | |
| 817 | // In some cases (such as bitcast), an operand | | |
| 818 | // may be the same MCValue as the result. If | | |
| 819 | // that operand died and was a register, it | | |
| 820 | // was freed by processDeath. We have to | | |
| 821 | // "re-allocate" the register. | | |
| 822 | if (self.register_manager.isRegFree(reg)) { | 814 | if (self.register_manager.isRegFree(reg)) { |
| 823 | self.register_manager.getRegAssumeFree(reg, inst); | 815 | self.register_manager.getRegAssumeFree(reg, inst); |
| 824 | } | 816 | } |
| 825 | }, | 817 | }, |
| | 818 | .register_overflow => |ro| { |
| | 819 | if (self.register_manager.isRegFree(ro.reg)) { |
| | 820 | self.register_manager.getRegAssumeFree(ro.reg, inst); |
| | 821 | } |
| | 822 | }, |
| 826 | else => {}, | 823 | else => {}, |
| 827 | } | 824 | } |
| 828 | } | 825 | } |
| ... | @@ -912,12 +909,12 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void | ... | @@ -912,12 +909,12 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 912 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); | 909 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); |
| 913 | const reg_mcv = self.getResolvedInstValue(inst); | 910 | const reg_mcv = self.getResolvedInstValue(inst); |
| 914 | switch (reg_mcv) { | 911 | switch (reg_mcv) { |
| 915 | .register, | 912 | .register => |other| { |
| 916 | .register_overflow_unsigned, | | |
| 917 | .register_overflow_signed, | | |
| 918 | => |other| { | | |
| 919 | assert(reg.to64() == other.to64()); | 913 | assert(reg.to64() == other.to64()); |
| 920 | }, | 914 | }, |
| | 915 | .register_overflow => |ro| { |
| | 916 | assert(reg.to64() == ro.reg.to64()); |
| | 917 | }, |
| 921 | else => {}, | 918 | else => {}, |
| 922 | } | 919 | } |
| 923 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 920 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| ... | @@ -929,9 +926,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { | ... | @@ -929,9 +926,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { |
| 929 | if (self.eflags_inst) |inst_to_save| { | 926 | if (self.eflags_inst) |inst_to_save| { |
| 930 | const mcv = self.getResolvedInstValue(inst_to_save); | 927 | const mcv = self.getResolvedInstValue(inst_to_save); |
| 931 | const new_mcv = switch (mcv) { | 928 | const new_mcv = switch (mcv) { |
| 932 | .register_overflow_signed, | 929 | .register_overflow => try self.allocRegOrMem(inst_to_save, false), |
| 933 | .register_overflow_unsigned, | | |
| 934 | => try self.allocRegOrMem(inst_to_save, false), | | |
| 935 | .eflags => try self.allocRegOrMem(inst_to_save, true), | 930 | .eflags => try self.allocRegOrMem(inst_to_save, true), |
| 936 | else => unreachable, | 931 | else => unreachable, |
| 937 | }; | 932 | }; |
| ... | @@ -947,9 +942,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { | ... | @@ -947,9 +942,7 @@ pub fn spillEflagsIfOccupied(self: *Self) !void { |
| 947 | // TODO consolidate with register manager and spillInstruction | 942 | // TODO consolidate with register manager and spillInstruction |
| 948 | // this call should really belong in the register manager! | 943 | // this call should really belong in the register manager! |
| 949 | switch (mcv) { | 944 | switch (mcv) { |
| 950 | .register_overflow_signed, | 945 | .register_overflow => |ro| self.register_manager.freeReg(ro.reg), |
| 951 | .register_overflow_unsigned, | | |
| 952 | => |reg| self.register_manager.freeReg(reg), | | |
| 953 | else => {}, | 946 | else => {}, |
| 954 | } | 947 | } |
| 955 | } | 948 | } |
| ... | @@ -1339,11 +1332,14 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1339,11 +1332,14 @@ fn airAddSubShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1339 | if (math.isPowerOfTwo(int_info.bits) and int_info.bits >= 8) { | 1332 | if (math.isPowerOfTwo(int_info.bits) and int_info.bits >= 8) { |
| 1340 | self.eflags_inst = inst; | 1333 | self.eflags_inst = inst; |
| 1341 | | 1334 | |
| 1342 | const result: MCValue = switch (int_info.signedness) { | 1335 | const cc: Condition = switch (int_info.signedness) { |
| 1343 | .signed => .{ .register_overflow_signed = partial.register }, | 1336 | .unsigned => .c, |
| 1344 | .unsigned => .{ .register_overflow_unsigned = partial.register }, | 1337 | .signed => .o, |
| 1345 | }; | 1338 | }; |
| 1346 | break :result result; | 1339 | break :result MCValue{ .register_overflow = .{ |
| | 1340 | .reg = partial.register, |
| | 1341 | .eflags = cc, |
| | 1342 | } }; |
| 1347 | } | 1343 | } |
| 1348 | | 1344 | |
| 1349 | self.eflags_inst = null; | 1345 | self.eflags_inst = null; |
| ... | @@ -1460,10 +1456,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1460,10 +1456,14 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1460 | const rhs = try self.resolveInst(bin_op.rhs); | 1456 | const rhs = try self.resolveInst(bin_op.rhs); |
| 1461 | | 1457 | |
| 1462 | const partial = try self.genMulDivBinOp(.mul, null, ty, lhs, rhs); | 1458 | const partial = try self.genMulDivBinOp(.mul, null, ty, lhs, rhs); |
| 1463 | break :result switch (int_info.signedness) { | 1459 | const cc: Condition = switch (int_info.signedness) { |
| 1464 | .signed => MCValue{ .register_overflow_signed = partial.register }, | 1460 | .unsigned => .c, |
| 1465 | .unsigned => MCValue{ .register_overflow_unsigned = partial.register }, | 1461 | .signed => .o, |
| 1466 | }; | 1462 | }; |
| | 1463 | break :result MCValue{ .register_overflow = .{ |
| | 1464 | .reg = partial.register, |
| | 1465 | .eflags = cc, |
| | 1466 | } }; |
| 1467 | } | 1467 | } |
| 1468 | | 1468 | |
| 1469 | try self.spillEflagsIfOccupied(); | 1469 | try self.spillEflagsIfOccupied(); |
| ... | @@ -2486,8 +2486,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2486,8 +2486,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2486 | .unreach => unreachable, | 2486 | .unreach => unreachable, |
| 2487 | .dead => unreachable, | 2487 | .dead => unreachable, |
| 2488 | .eflags => unreachable, | 2488 | .eflags => unreachable, |
| 2489 | .register_overflow_unsigned => unreachable, | 2489 | .register_overflow => unreachable, |
| 2490 | .register_overflow_signed => unreachable, | | |
| 2491 | .immediate => |imm| { | 2490 | .immediate => |imm| { |
| 2492 | try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }); | 2491 | try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }); |
| 2493 | }, | 2492 | }, |
| ... | @@ -2610,8 +2609,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2610,8 +2609,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2610 | .unreach => unreachable, | 2609 | .unreach => unreachable, |
| 2611 | .dead => unreachable, | 2610 | .dead => unreachable, |
| 2612 | .eflags => unreachable, | 2611 | .eflags => unreachable, |
| 2613 | .register_overflow_unsigned => unreachable, | 2612 | .register_overflow => unreachable, |
| 2614 | .register_overflow_signed => unreachable, | | |
| 2615 | .immediate => |imm| { | 2613 | .immediate => |imm| { |
| 2616 | try self.setRegOrMem(value_ty, .{ .memory = imm }, value); | 2614 | try self.setRegOrMem(value_ty, .{ .memory = imm }, value); |
| 2617 | }, | 2615 | }, |
| ... | @@ -2997,31 +2995,24 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2997,31 +2995,24 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2997 | | 2995 | |
| 2998 | break :result dst_mcv; | 2996 | break :result dst_mcv; |
| 2999 | }, | 2997 | }, |
| 3000 | .register_overflow_unsigned, | 2998 | .register_overflow => |ro| { |
| 3001 | .register_overflow_signed, | | |
| 3002 | => |reg| { | | |
| 3003 | switch (index) { | 2999 | switch (index) { |
| 3004 | 0 => { | 3000 | 0 => { |
| 3005 | // Get wrapped value for overflow operation. | 3001 | // Get wrapped value for overflow operation. |
| 3006 | break :result MCValue{ .register = reg }; | 3002 | break :result MCValue{ .register = ro.reg }; |
| 3007 | }, | 3003 | }, |
| 3008 | 1 => { | 3004 | 1 => { |
| 3009 | // Get overflow bit. | 3005 | // Get overflow bit. |
| 3010 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); | 3006 | const reg_lock = self.register_manager.lockRegAssumeUnused(ro.reg); |
| 3011 | defer self.register_manager.unlockReg(reg_lock); | 3007 | defer self.register_manager.unlockReg(reg_lock); |
| 3012 | | 3008 | |
| 3013 | const dst_reg = try self.register_manager.allocReg(inst, gp); | 3009 | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 3014 | const cc: Condition = switch (mcv) { | | |
| 3015 | .register_overflow_unsigned => .c, | | |
| 3016 | .register_overflow_signed => .o, | | |
| 3017 | else => unreachable, | | |
| 3018 | }; | | |
| 3019 | _ = try self.addInst(.{ | 3010 | _ = try self.addInst(.{ |
| 3020 | .tag = .cond_set_byte, | 3011 | .tag = .cond_set_byte, |
| 3021 | .ops = Mir.Inst.Ops.encode(.{ | 3012 | .ops = Mir.Inst.Ops.encode(.{ |
| 3022 | .reg1 = dst_reg.to8(), | 3013 | .reg1 = dst_reg.to8(), |
| 3023 | }), | 3014 | }), |
| 3024 | .data = .{ .cc = cc }, | 3015 | .data = .{ .cc = ro.eflags }, |
| 3025 | }); | 3016 | }); |
| 3026 | break :result MCValue{ .register = dst_reg.to8() }; | 3017 | break :result MCValue{ .register = dst_reg.to8() }; |
| 3027 | }, | 3018 | }, |
| ... | @@ -3449,15 +3440,13 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3449,15 +3440,13 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3449 | .undef => unreachable, | 3440 | .undef => unreachable, |
| 3450 | .dead, .unreach, .immediate => unreachable, | 3441 | .dead, .unreach, .immediate => unreachable, |
| 3451 | .eflags => unreachable, | 3442 | .eflags => unreachable, |
| 3452 | .register_overflow_unsigned => unreachable, | 3443 | .register_overflow => unreachable, |
| 3453 | .register_overflow_signed => unreachable, | | |
| 3454 | .register => |dst_reg| { | 3444 | .register => |dst_reg| { |
| 3455 | switch (src_mcv) { | 3445 | switch (src_mcv) { |
| 3456 | .none => unreachable, | 3446 | .none => unreachable, |
| 3457 | .undef => unreachable, | 3447 | .undef => unreachable, |
| 3458 | .dead, .unreach => unreachable, | 3448 | .dead, .unreach => unreachable, |
| 3459 | .register_overflow_unsigned => unreachable, | 3449 | .register_overflow => unreachable, |
| 3460 | .register_overflow_signed => unreachable, | | |
| 3461 | .ptr_stack_offset => { | 3450 | .ptr_stack_offset => { |
| 3462 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); | 3451 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| 3463 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); | 3452 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | @@ -3564,8 +3553,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu | ... | @@ -3564,8 +3553,7 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3564 | .none => unreachable, | 3553 | .none => unreachable, |
| 3565 | .undef => unreachable, | 3554 | .undef => unreachable, |
| 3566 | .dead, .unreach => unreachable, | 3555 | .dead, .unreach => unreachable, |
| 3567 | .register_overflow_unsigned => unreachable, | 3556 | .register_overflow => unreachable, |
| 3568 | .register_overflow_signed => unreachable, | | |
| 3569 | .register => |src_reg| { | 3557 | .register => |src_reg| { |
| 3570 | _ = try self.addInst(.{ | 3558 | _ = try self.addInst(.{ |
| 3571 | .tag = mir_tag, | 3559 | .tag = mir_tag, |
| ... | @@ -3640,16 +3628,14 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3640,16 +3628,14 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3640 | .dead, .unreach, .immediate => unreachable, | 3628 | .dead, .unreach, .immediate => unreachable, |
| 3641 | .eflags => unreachable, | 3629 | .eflags => unreachable, |
| 3642 | .ptr_stack_offset => unreachable, | 3630 | .ptr_stack_offset => unreachable, |
| 3643 | .register_overflow_unsigned => unreachable, | 3631 | .register_overflow => unreachable, |
| 3644 | .register_overflow_signed => unreachable, | | |
| 3645 | .register => |dst_reg| { | 3632 | .register => |dst_reg| { |
| 3646 | switch (src_mcv) { | 3633 | switch (src_mcv) { |
| 3647 | .none => unreachable, | 3634 | .none => unreachable, |
| 3648 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), | 3635 | .undef => try self.genSetReg(dst_ty, dst_reg, .undef), |
| 3649 | .dead, .unreach => unreachable, | 3636 | .dead, .unreach => unreachable, |
| 3650 | .ptr_stack_offset => unreachable, | 3637 | .ptr_stack_offset => unreachable, |
| 3651 | .register_overflow_unsigned => unreachable, | 3638 | .register_overflow => unreachable, |
| 3652 | .register_overflow_signed => unreachable, | | |
| 3653 | .register => |src_reg| { | 3639 | .register => |src_reg| { |
| 3654 | // register, register | 3640 | // register, register |
| 3655 | _ = try self.addInst(.{ | 3641 | _ = try self.addInst(.{ |
| ... | @@ -3708,8 +3694,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -3708,8 +3694,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3708 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), | 3694 | .undef => return self.genSetStack(dst_ty, off, .undef, .{}), |
| 3709 | .dead, .unreach => unreachable, | 3695 | .dead, .unreach => unreachable, |
| 3710 | .ptr_stack_offset => unreachable, | 3696 | .ptr_stack_offset => unreachable, |
| 3711 | .register_overflow_unsigned => unreachable, | 3697 | .register_overflow => unreachable, |
| 3712 | .register_overflow_signed => unreachable, | | |
| 3713 | .register => |src_reg| { | 3698 | .register => |src_reg| { |
| 3714 | // copy dst to a register | 3699 | // copy dst to a register |
| 3715 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | 3700 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| ... | @@ -3915,8 +3900,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -3915,8 +3900,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3915 | .got_load => unreachable, | 3900 | .got_load => unreachable, |
| 3916 | .direct_load => unreachable, | 3901 | .direct_load => unreachable, |
| 3917 | .eflags => unreachable, | 3902 | .eflags => unreachable, |
| 3918 | .register_overflow_signed => unreachable, | 3903 | .register_overflow => unreachable, |
| 3919 | .register_overflow_unsigned => unreachable, | | |
| 3920 | } | 3904 | } |
| 3921 | } | 3905 | } |
| 3922 | | 3906 | |
| ... | @@ -5291,9 +5275,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE | ... | @@ -5291,9 +5275,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5291 | .{ .dest_stack_base = .rsp }, | 5275 | .{ .dest_stack_base = .rsp }, |
| 5292 | ); | 5276 | ); |
| 5293 | }, | 5277 | }, |
| 5294 | .register_overflow_unsigned, | 5278 | .register_overflow => return self.fail("TODO genSetStackArg for register with overflow bit", .{}), |
| 5295 | .register_overflow_signed, | | |
| 5296 | => return self.fail("TODO genSetStackArg for register with overflow bit", .{}), | | |
| 5297 | .eflags => { | 5279 | .eflags => { |
| 5298 | const reg = try self.copyToTmpRegister(ty, mcv); | 5280 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 5299 | return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); | 5281 | return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); |
| ... | @@ -5429,29 +5411,22 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl | ... | @@ -5429,29 +5411,22 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5429 | ), | 5411 | ), |
| 5430 | } | 5412 | } |
| 5431 | }, | 5413 | }, |
| 5432 | .register_overflow_unsigned, | 5414 | .register_overflow => |ro| { |
| 5433 | .register_overflow_signed, | 5415 | const reg_lock = self.register_manager.lockReg(ro.reg); |
| 5434 | => |reg| { | | |
| 5435 | const reg_lock = self.register_manager.lockReg(reg); | | |
| 5436 | defer if (reg_lock) |lock| self.register_manager.unlockReg(lock); | 5416 | defer if (reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 5437 | | 5417 | |
| 5438 | const wrapped_ty = ty.structFieldType(0); | 5418 | const wrapped_ty = ty.structFieldType(0); |
| 5439 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }, .{}); | 5419 | try self.genSetStack(wrapped_ty, stack_offset, .{ .register = ro.reg }, .{}); |
| 5440 | | 5420 | |
| 5441 | const overflow_bit_ty = ty.structFieldType(1); | 5421 | const overflow_bit_ty = ty.structFieldType(1); |
| 5442 | const overflow_bit_offset = ty.structFieldOffset(1, self.target.*); | 5422 | const overflow_bit_offset = ty.structFieldOffset(1, self.target.*); |
| 5443 | const tmp_reg = try self.register_manager.allocReg(null, gp); | 5423 | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 5444 | const cc: Condition = switch (mcv) { | | |
| 5445 | .register_overflow_unsigned => .c, | | |
| 5446 | .register_overflow_signed => .o, | | |
| 5447 | else => unreachable, | | |
| 5448 | }; | | |
| 5449 | _ = try self.addInst(.{ | 5424 | _ = try self.addInst(.{ |
| 5450 | .tag = .cond_set_byte, | 5425 | .tag = .cond_set_byte, |
| 5451 | .ops = Mir.Inst.Ops.encode(.{ | 5426 | .ops = Mir.Inst.Ops.encode(.{ |
| 5452 | .reg1 = tmp_reg.to8(), | 5427 | .reg1 = tmp_reg.to8(), |
| 5453 | }), | 5428 | }), |
| 5454 | .data = .{ .cc = cc }, | 5429 | .data = .{ .cc = ro.eflags }, |
| 5455 | }); | 5430 | }); |
| 5456 | | 5431 | |
| 5457 | return self.genSetStack( | 5432 | return self.genSetStack( |
| ... | @@ -5956,9 +5931,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -5956,9 +5931,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 5956 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 5931 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5957 | switch (mcv) { | 5932 | switch (mcv) { |
| 5958 | .dead => unreachable, | 5933 | .dead => unreachable, |
| 5959 | .register_overflow_unsigned, | 5934 | .register_overflow => unreachable, |
| 5960 | .register_overflow_signed, | | |
| 5961 | => unreachable, | | |
| 5962 | .ptr_stack_offset => |off| { | 5935 | .ptr_stack_offset => |off| { |
| 5963 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { | 5936 | if (off < std.math.minInt(i32) or off > std.math.maxInt(i32)) { |
| 5964 | return self.fail("stack offset too large", .{}); | 5937 | return self.fail("stack offset too large", .{}); |