| ... | @@ -93,8 +93,8 @@ register_manager: RegisterManager = .{}, | ... | @@ -93,8 +93,8 @@ register_manager: RegisterManager = .{}, |
| 93 | /// Maps offset to what is stored there. | 93 | /// Maps offset to what is stored there. |
| 94 | stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{}, | 94 | stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{}, |
| 95 | | 95 | |
| 96 | /// Tracks the current instruction allocated to the compare flags | 96 | /// Tracks the current instruction allocated to the condition flags |
| 97 | compare_flags_inst: ?Air.Inst.Index = null, | 97 | condition_flags_inst: ?Air.Inst.Index = null, |
| 98 | | 98 | |
| 99 | /// Offset from the stack base, representing the end of the stack frame. | 99 | /// Offset from the stack base, representing the end of the stack frame. |
| 100 | max_end_stack: u32 = 0, | 100 | max_end_stack: u32 = 0, |
| ... | @@ -141,16 +141,11 @@ const MCValue = union(enum) { | ... | @@ -141,16 +141,11 @@ const MCValue = union(enum) { |
| 141 | stack_offset: u32, | 141 | stack_offset: u32, |
| 142 | /// The value is a pointer to one of the stack variables (payload is stack offset). | 142 | /// The value is a pointer to one of the stack variables (payload is stack offset). |
| 143 | ptr_stack_offset: u32, | 143 | ptr_stack_offset: u32, |
| 144 | /// The value is in the specified CCR assuming an unsigned operation, | 144 | /// The value is in the specified CCR. The value is 1 (if |
| 145 | /// with the operator applied on top of it. | 145 | /// the type is u1) or true (if the type in bool) iff the |
| 146 | compare_flags_unsigned: struct { | 146 | /// specified condition is true. |
| 147 | cmp: math.CompareOperator, | 147 | condition_flags: struct { |
| 148 | ccr: Instruction.CCR, | 148 | cond: Instruction.Condition, |
| 149 | }, | | |
| 150 | /// The value is in the specified CCR assuming an signed operation, | | |
| 151 | /// with the operator applied on top of it. | | |
| 152 | compare_flags_signed: struct { | | |
| 153 | cmp: math.CompareOperator, | | |
| 154 | ccr: Instruction.CCR, | 149 | ccr: Instruction.CCR, |
| 155 | }, | 150 | }, |
| 156 | | 151 | |
| ... | @@ -738,8 +733,8 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -738,8 +733,8 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 738 | else => unreachable, | 733 | else => unreachable, |
| 739 | }; | 734 | }; |
| 740 | | 735 | |
| 741 | try self.spillCompareFlagsIfOccupied(); | 736 | try self.spillConditionFlagsIfOccupied(); |
| 742 | self.compare_flags_inst = inst; | 737 | self.condition_flags_inst = inst; |
| 743 | | 738 | |
| 744 | const dest = blk: { | 739 | const dest = blk: { |
| 745 | if (rhs_immediate_ok) { | 740 | if (rhs_immediate_ok) { |
| ... | @@ -1072,7 +1067,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -1072,7 +1067,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1072 | | 1067 | |
| 1073 | // CCR is volatile across function calls | 1068 | // CCR is volatile across function calls |
| 1074 | // (SCD 2.4.1, page 3P-10) | 1069 | // (SCD 2.4.1, page 3P-10) |
| 1075 | try self.spillCompareFlagsIfOccupied(); | 1070 | try self.spillConditionFlagsIfOccupied(); |
| 1076 | | 1071 | |
| 1077 | for (info.args) |mc_arg, arg_i| { | 1072 | for (info.args) |mc_arg, arg_i| { |
| 1078 | const arg = args[arg_i]; | 1073 | const arg = args[arg_i]; |
| ... | @@ -1208,12 +1203,18 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -1208,12 +1203,18 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1208 | .inst = inst, | 1203 | .inst = inst, |
| 1209 | }); | 1204 | }); |
| 1210 | | 1205 | |
| 1211 | try self.spillCompareFlagsIfOccupied(); | 1206 | try self.spillConditionFlagsIfOccupied(); |
| 1212 | self.compare_flags_inst = inst; | 1207 | self.condition_flags_inst = inst; |
| 1213 | | 1208 | |
| 1214 | break :result switch (int_info.signedness) { | 1209 | break :result switch (int_info.signedness) { |
| 1215 | .signed => MCValue{ .compare_flags_signed = .{ .cmp = op, .ccr = .xcc } }, | 1210 | .signed => MCValue{ .condition_flags = .{ |
| 1216 | .unsigned => MCValue{ .compare_flags_unsigned = .{ .cmp = op, .ccr = .xcc } }, | 1211 | .cond = .{ .icond = Instruction.ICondition.fromCompareOperatorSigned(op) }, |
| | 1212 | .ccr = .xcc, |
| | 1213 | } }, |
| | 1214 | .unsigned => MCValue{ .condition_flags = .{ |
| | 1215 | .cond = .{ .icond = Instruction.ICondition.fromCompareOperatorUnsigned(op) }, |
| | 1216 | .ccr = .xcc, |
| | 1217 | } }, |
| 1217 | }; | 1218 | }; |
| 1218 | } else { | 1219 | } else { |
| 1219 | return self.fail("TODO SPARCv9 cmp for ints > 64 bits", .{}); | 1220 | return self.fail("TODO SPARCv9 cmp for ints > 64 bits", .{}); |
| ... | @@ -1224,7 +1225,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -1224,7 +1225,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 1224 | | 1225 | |
| 1225 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | 1226 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1226 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 1227 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 1227 | const cond = try self.resolveInst(pl_op.operand); | 1228 | const condition = try self.resolveInst(pl_op.operand); |
| 1228 | const extra = self.air.extraData(Air.CondBr, pl_op.payload); | 1229 | const extra = self.air.extraData(Air.CondBr, pl_op.payload); |
| 1229 | const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len]; | 1230 | const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len]; |
| 1230 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 1231 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| ... | @@ -1232,39 +1233,22 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1232,39 +1233,22 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1232 | | 1233 | |
| 1233 | // Here we either emit a BPcc for branching on CCR content, | 1234 | // Here we either emit a BPcc for branching on CCR content, |
| 1234 | // or emit a BPr to branch on register content. | 1235 | // or emit a BPr to branch on register content. |
| 1235 | const reloc: Mir.Inst.Index = switch (cond) { | 1236 | const reloc: Mir.Inst.Index = switch (condition) { |
| 1236 | .compare_flags_signed, | 1237 | .condition_flags => |flags| try self.addInst(.{ |
| 1237 | .compare_flags_unsigned, | | |
| 1238 | => try self.addInst(.{ | | |
| 1239 | .tag = .bpcc, | 1238 | .tag = .bpcc, |
| 1240 | .data = .{ | 1239 | .data = .{ |
| 1241 | .branch_predict_int = .{ | 1240 | .branch_predict_int = .{ |
| 1242 | .ccr = switch (cond) { | 1241 | .ccr = flags.ccr, |
| 1243 | .compare_flags_signed => |cmp_op| cmp_op.ccr, | 1242 | // Here we map to the opposite condition because the jump is to the false branch. |
| 1244 | .compare_flags_unsigned => |cmp_op| cmp_op.ccr, | 1243 | .cond = flags.cond.icond.negate(), |
| 1245 | else => unreachable, | | |
| 1246 | }, | | |
| 1247 | .cond = switch (cond) { | | |
| 1248 | .compare_flags_signed => |cmp_op| blk: { | | |
| 1249 | // Here we map to the opposite condition because the jump is to the false branch. | | |
| 1250 | const condition = Instruction.ICondition.fromCompareOperatorSigned(cmp_op.cmp); | | |
| 1251 | break :blk condition.negate(); | | |
| 1252 | }, | | |
| 1253 | .compare_flags_unsigned => |cmp_op| blk: { | | |
| 1254 | // Here we map to the opposite condition because the jump is to the false branch. | | |
| 1255 | const condition = Instruction.ICondition.fromCompareOperatorUnsigned(cmp_op.cmp); | | |
| 1256 | break :blk condition.negate(); | | |
| 1257 | }, | | |
| 1258 | else => unreachable, | | |
| 1259 | }, | | |
| 1260 | .inst = undefined, // Will be filled by performReloc | 1244 | .inst = undefined, // Will be filled by performReloc |
| 1261 | }, | 1245 | }, |
| 1262 | }, | 1246 | }, |
| 1263 | }), | 1247 | }), |
| 1264 | else => blk: { | 1248 | else => blk: { |
| 1265 | const reg = switch (cond) { | 1249 | const reg = switch (condition) { |
| 1266 | .register => |r| r, | 1250 | .register => |r| r, |
| 1267 | else => try self.copyToTmpRegister(Type.bool, cond), | 1251 | else => try self.copyToTmpRegister(Type.bool, condition), |
| 1268 | }; | 1252 | }; |
| 1269 | | 1253 | |
| 1270 | break :blk try self.addInst(.{ | 1254 | break :blk try self.addInst(.{ |
| ... | @@ -1305,7 +1289,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1305,7 +1289,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1305 | var parent_stack = try self.stack.clone(self.gpa); | 1289 | var parent_stack = try self.stack.clone(self.gpa); |
| 1306 | defer parent_stack.deinit(self.gpa); | 1290 | defer parent_stack.deinit(self.gpa); |
| 1307 | const parent_registers = self.register_manager.registers; | 1291 | const parent_registers = self.register_manager.registers; |
| 1308 | const parent_compare_flags_inst = self.compare_flags_inst; | 1292 | const parent_condition_flags_inst = self.condition_flags_inst; |
| 1309 | | 1293 | |
| 1310 | try self.branch_stack.append(.{}); | 1294 | try self.branch_stack.append(.{}); |
| 1311 | errdefer { | 1295 | errdefer { |
| ... | @@ -1324,7 +1308,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1324,7 +1308,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1324 | defer saved_then_branch.deinit(self.gpa); | 1308 | defer saved_then_branch.deinit(self.gpa); |
| 1325 | | 1309 | |
| 1326 | self.register_manager.registers = parent_registers; | 1310 | self.register_manager.registers = parent_registers; |
| 1327 | self.compare_flags_inst = parent_compare_flags_inst; | 1311 | self.condition_flags_inst = parent_condition_flags_inst; |
| 1328 | | 1312 | |
| 1329 | self.stack.deinit(self.gpa); | 1313 | self.stack.deinit(self.gpa); |
| 1330 | self.stack = parent_stack; | 1314 | self.stack = parent_stack; |
| ... | @@ -1537,37 +1521,13 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1537,37 +1521,13 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1537 | switch (operand) { | 1521 | switch (operand) { |
| 1538 | .dead => unreachable, | 1522 | .dead => unreachable, |
| 1539 | .unreach => unreachable, | 1523 | .unreach => unreachable, |
| 1540 | .compare_flags_unsigned => |op| { | 1524 | .condition_flags => |op| { |
| 1541 | const r = MCValue{ | 1525 | break :result MCValue{ |
| 1542 | .compare_flags_unsigned = .{ | 1526 | .condition_flags = .{ |
| 1543 | .cmp = switch (op.cmp) { | 1527 | .cond = op.cond.negate(), |
| 1544 | .gte => .lt, | | |
| 1545 | .gt => .lte, | | |
| 1546 | .neq => .eq, | | |
| 1547 | .lt => .gte, | | |
| 1548 | .lte => .gt, | | |
| 1549 | .eq => .neq, | | |
| 1550 | }, | | |
| 1551 | .ccr = op.ccr, | 1528 | .ccr = op.ccr, |
| 1552 | }, | 1529 | }, |
| 1553 | }; | 1530 | }; |
| 1554 | break :result r; | | |
| 1555 | }, | | |
| 1556 | .compare_flags_signed => |op| { | | |
| 1557 | const r = MCValue{ | | |
| 1558 | .compare_flags_signed = .{ | | |
| 1559 | .cmp = switch (op.cmp) { | | |
| 1560 | .gte => .lt, | | |
| 1561 | .gt => .lte, | | |
| 1562 | .neq => .eq, | | |
| 1563 | .lt => .gte, | | |
| 1564 | .lte => .gt, | | |
| 1565 | .eq => .neq, | | |
| 1566 | }, | | |
| 1567 | .ccr = op.ccr, | | |
| 1568 | }, | | |
| 1569 | }; | | |
| 1570 | break :result r; | | |
| 1571 | }, | 1531 | }, |
| 1572 | else => { | 1532 | else => { |
| 1573 | switch (operand_ty.zigTypeTag()) { | 1533 | switch (operand_ty.zigTypeTag()) { |
| ... | @@ -2667,20 +2627,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -2667,20 +2627,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2667 | switch (mcv) { | 2627 | switch (mcv) { |
| 2668 | .dead => unreachable, | 2628 | .dead => unreachable, |
| 2669 | .unreach, .none => return, // Nothing to do. | 2629 | .unreach, .none => return, // Nothing to do. |
| 2670 | .compare_flags_signed, | 2630 | .condition_flags => |op| { |
| 2671 | .compare_flags_unsigned, | 2631 | const condition = op.cond; |
| 2672 | => { | 2632 | const ccr = op.ccr; |
| 2673 | const condition = switch (mcv) { | | |
| 2674 | .compare_flags_unsigned => |op| Instruction.ICondition.fromCompareOperatorUnsigned(op.cmp), | | |
| 2675 | .compare_flags_signed => |op| Instruction.ICondition.fromCompareOperatorSigned(op.cmp), | | |
| 2676 | else => unreachable, | | |
| 2677 | }; | | |
| 2678 | | 2633 | |
| 2679 | const ccr = switch (mcv) { | | |
| 2680 | .compare_flags_unsigned => |op| op.ccr, | | |
| 2681 | .compare_flags_signed => |op| op.ccr, | | |
| 2682 | else => unreachable, | | |
| 2683 | }; | | |
| 2684 | // TODO handle floating point CCRs | 2634 | // TODO handle floating point CCRs |
| 2685 | assert(ccr == .xcc or ccr == .icc); | 2635 | assert(ccr == .xcc or ccr == .icc); |
| 2686 | | 2636 | |
| ... | @@ -2700,7 +2650,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -2700,7 +2650,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2700 | .data = .{ | 2650 | .data = .{ |
| 2701 | .conditional_move = .{ | 2651 | .conditional_move = .{ |
| 2702 | .ccr = ccr, | 2652 | .ccr = ccr, |
| 2703 | .cond = .{ .icond = condition }, | 2653 | .cond = condition, |
| 2704 | .is_imm = true, | 2654 | .is_imm = true, |
| 2705 | .rd = reg, | 2655 | .rd = reg, |
| 2706 | .rs2_or_imm = .{ .imm = 1 }, | 2656 | .rs2_or_imm = .{ .imm = 1 }, |
| ... | @@ -2874,8 +2824,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2874,8 +2824,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2874 | else => return self.fail("TODO implement memset", .{}), | 2824 | else => return self.fail("TODO implement memset", .{}), |
| 2875 | } | 2825 | } |
| 2876 | }, | 2826 | }, |
| 2877 | .compare_flags_unsigned, | 2827 | .condition_flags, |
| 2878 | .compare_flags_signed, | | |
| 2879 | .immediate, | 2828 | .immediate, |
| 2880 | .ptr_stack_offset, | 2829 | .ptr_stack_offset, |
| 2881 | => { | 2830 | => { |
| ... | @@ -3103,7 +3052,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { | ... | @@ -3103,7 +3052,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3103 | } }, | 3052 | } }, |
| 3104 | }); | 3053 | }); |
| 3105 | | 3054 | |
| 3106 | return MCValue{ .compare_flags_unsigned = .{ .cmp = .gt, .ccr = .xcc } }; | 3055 | return MCValue{ .condition_flags = .{ .cond = .{ .icond = .gu }, .ccr = .xcc } }; |
| 3107 | } else { | 3056 | } else { |
| 3108 | return self.fail("TODO isErr for errors with size > 8", .{}); | 3057 | return self.fail("TODO isErr for errors with size > 8", .{}); |
| 3109 | } | 3058 | } |
| ... | @@ -3116,9 +3065,8 @@ fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue { | ... | @@ -3116,9 +3065,8 @@ fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 3116 | // Call isErr, then negate the result. | 3065 | // Call isErr, then negate the result. |
| 3117 | const is_err_result = try self.isErr(ty, operand); | 3066 | const is_err_result = try self.isErr(ty, operand); |
| 3118 | switch (is_err_result) { | 3067 | switch (is_err_result) { |
| 3119 | .compare_flags_unsigned => |op| { | 3068 | .condition_flags => |op| { |
| 3120 | assert(op.cmp == .gt); | 3069 | return MCValue{ .condition_flags = .{ .cond = op.cond.negate(), .ccr = op.ccr } }; |
| 3121 | return MCValue{ .compare_flags_unsigned = .{ .cmp = .lte, .ccr = op.ccr } }; | | |
| 3122 | }, | 3070 | }, |
| 3123 | .immediate => |imm| { | 3071 | .immediate => |imm| { |
| 3124 | assert(imm == 0); | 3072 | assert(imm == 0); |
| ... | @@ -3168,8 +3116,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -3168,8 +3116,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3168 | .undef => unreachable, | 3116 | .undef => unreachable, |
| 3169 | .unreach => unreachable, | 3117 | .unreach => unreachable, |
| 3170 | .dead => unreachable, | 3118 | .dead => unreachable, |
| 3171 | .compare_flags_unsigned, | 3119 | .condition_flags, |
| 3172 | .compare_flags_signed, | | |
| 3173 | .register_with_overflow, | 3120 | .register_with_overflow, |
| 3174 | => unreachable, // cannot hold an address | 3121 | => unreachable, // cannot hold an address |
| 3175 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), | 3122 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), |
| ... | @@ -3181,7 +3128,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -3181,7 +3128,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 3181 | switch (dst_mcv) { | 3128 | switch (dst_mcv) { |
| 3182 | .dead => unreachable, | 3129 | .dead => unreachable, |
| 3183 | .undef => unreachable, | 3130 | .undef => unreachable, |
| 3184 | .compare_flags_signed, .compare_flags_unsigned => unreachable, | 3131 | .condition_flags => unreachable, |
| 3185 | .register => |dst_reg| { | 3132 | .register => |dst_reg| { |
| 3186 | try self.genLoad(dst_reg, addr_reg, i13, 0, elem_size); | 3133 | try self.genLoad(dst_reg, addr_reg, i13, 0, elem_size); |
| 3187 | }, | 3134 | }, |
| ... | @@ -3277,10 +3224,10 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { | ... | @@ -3277,10 +3224,10 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 3277 | }, | 3224 | }, |
| 3278 | .register_with_overflow => |rwo| { | 3225 | .register_with_overflow => |rwo| { |
| 3279 | self.register_manager.freeReg(rwo.reg); | 3226 | self.register_manager.freeReg(rwo.reg); |
| 3280 | self.compare_flags_inst = null; | 3227 | self.condition_flags_inst = null; |
| 3281 | }, | 3228 | }, |
| 3282 | .compare_flags_signed, .compare_flags_unsigned => { | 3229 | .condition_flags => { |
| 3283 | self.compare_flags_inst = null; | 3230 | self.condition_flags_inst = null; |
| 3284 | }, | 3231 | }, |
| 3285 | else => {}, // TODO process stack allocation death | 3232 | else => {}, // TODO process stack allocation death |
| 3286 | } | 3233 | } |
| ... | @@ -3474,15 +3421,13 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | ... | @@ -3474,15 +3421,13 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 3474 | } | 3421 | } |
| 3475 | } | 3422 | } |
| 3476 | | 3423 | |
| 3477 | /// Save the current instruction stored in the compare flags if | 3424 | /// Save the current instruction stored in the condition flags if |
| 3478 | /// occupied | 3425 | /// occupied |
| 3479 | fn spillCompareFlagsIfOccupied(self: *Self) !void { | 3426 | fn spillConditionFlagsIfOccupied(self: *Self) !void { |
| 3480 | if (self.compare_flags_inst) |inst_to_save| { | 3427 | if (self.condition_flags_inst) |inst_to_save| { |
| 3481 | const mcv = self.getResolvedInstValue(inst_to_save); | 3428 | const mcv = self.getResolvedInstValue(inst_to_save); |
| 3482 | const new_mcv = switch (mcv) { | 3429 | const new_mcv = switch (mcv) { |
| 3483 | .compare_flags_signed, | 3430 | .condition_flags => try self.allocRegOrMem(inst_to_save, true), |
| 3484 | .compare_flags_unsigned, | | |
| 3485 | => try self.allocRegOrMem(inst_to_save, true), | | |
| 3486 | .register_with_overflow => try self.allocRegOrMem(inst_to_save, false), | 3431 | .register_with_overflow => try self.allocRegOrMem(inst_to_save, false), |
| 3487 | else => unreachable, // mcv doesn't occupy the compare flags | 3432 | else => unreachable, // mcv doesn't occupy the compare flags |
| 3488 | }; | 3433 | }; |
| ... | @@ -3493,7 +3438,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { | ... | @@ -3493,7 +3438,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 3493 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 3438 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 3494 | try branch.inst_table.put(self.gpa, inst_to_save, new_mcv); | 3439 | try branch.inst_table.put(self.gpa, inst_to_save, new_mcv); |
| 3495 | | 3440 | |
| 3496 | self.compare_flags_inst = null; | 3441 | self.condition_flags_inst = null; |
| 3497 | | 3442 | |
| 3498 | // TODO consolidate with register manager and spillInstruction | 3443 | // TODO consolidate with register manager and spillInstruction |
| 3499 | // this call should really belong in the register manager! | 3444 | // this call should really belong in the register manager! |
| ... | @@ -3522,8 +3467,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3522,8 +3467,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3522 | .undef => unreachable, | 3467 | .undef => unreachable, |
| 3523 | .unreach => unreachable, | 3468 | .unreach => unreachable, |
| 3524 | .dead => unreachable, | 3469 | .dead => unreachable, |
| 3525 | .compare_flags_unsigned, | 3470 | .condition_flags, |
| 3526 | .compare_flags_signed, | | |
| 3527 | .register_with_overflow, | 3471 | .register_with_overflow, |
| 3528 | => unreachable, // cannot hold an address | 3472 | => unreachable, // cannot hold an address |
| 3529 | .immediate => |imm| { | 3473 | .immediate => |imm| { |