| ... | ... | @@ -1099,15 +1099,22 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1099 | 1099 | |
| 1100 | 1100 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1101 | 1101 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1102 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement unwrap error union error for {}", .{self.target.cpu.arch}); |
| 1102 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1103 | const error_union_ty = self.air.typeOf(ty_op.operand); |
| 1104 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1105 | const mcv = try self.resolveInst(ty_op.operand); |
| 1106 | if (!payload_ty.hasCodeGenBits()) break :result mcv; |
| 1107 | |
| 1108 | return self.fail("TODO implement unwrap error union error for non-empty payloads", .{}); |
| 1109 | }; |
| 1103 | 1110 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1104 | 1111 | } |
| 1105 | 1112 | |
| 1106 | 1113 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1107 | 1114 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1108 | 1115 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1109 | | const err_ty = self.air.typeOf(ty_op.operand); |
| 1110 | | const payload_ty = err_ty.errorUnionPayload(); |
| 1116 | const error_union_ty = self.air.typeOf(ty_op.operand); |
| 1117 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1111 | 1118 | if (!payload_ty.hasCodeGenBits()) break :result MCValue.none; |
| 1112 | 1119 | |
| 1113 | 1120 | return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{}); |
| ... | ... | @@ -2411,19 +2418,26 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2411 | 2418 | |
| 2412 | 2419 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2413 | 2420 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2414 | | if (self.liveness.isUnused(inst)) |
| 2415 | | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2416 | | const ty = self.air.typeOf(bin_op.lhs); |
| 2417 | | assert(ty.eql(self.air.typeOf(bin_op.rhs))); |
| 2418 | | if (ty.zigTypeTag() == .ErrorSet) |
| 2419 | | return self.fail("TODO implement cmp for errors", .{}); |
| 2421 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2422 | const lhs = try self.resolveInst(bin_op.lhs); |
| 2423 | const rhs = try self.resolveInst(bin_op.rhs); |
| 2424 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 2420 | 2425 | |
| 2421 | | try self.spillCompareFlagsIfOccupied(); |
| 2422 | | self.compare_flags_inst = inst; |
| 2426 | if (lhs_ty.abiSize(self.target.*) > 4) { |
| 2427 | return self.fail("TODO cmp for types with size > 4", .{}); |
| 2428 | } |
| 2429 | |
| 2430 | const signedness: std.builtin.Signedness = blk: { |
| 2431 | // by default we tell the operand type is unsigned (i.e. bools and enum values) |
| 2432 | if (lhs_ty.zigTypeTag() != .Int) break :blk .unsigned; |
| 2433 | |
| 2434 | // incase of an actual integer, we emit the correct signedness |
| 2435 | break :blk lhs_ty.intInfo(self.target.*).signedness; |
| 2436 | }; |
| 2437 | |
| 2438 | try self.spillCompareFlagsIfOccupied(); |
| 2439 | self.compare_flags_inst = inst; |
| 2423 | 2440 | |
| 2424 | | const lhs = try self.resolveInst(bin_op.lhs); |
| 2425 | | const rhs = try self.resolveInst(bin_op.rhs); |
| 2426 | | const result: MCValue = result: { |
| 2427 | 2441 | const lhs_is_register = lhs == .register; |
| 2428 | 2442 | const rhs_is_register = rhs == .register; |
| 2429 | 2443 | // lhs should always be a register |
| ... | ... | @@ -2457,11 +2471,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2457 | 2471 | // Move the operands to the newly allocated registers |
| 2458 | 2472 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 2459 | 2473 | if (lhs_mcv == .register and !lhs_is_register) { |
| 2460 | | try self.genSetReg(ty, lhs_mcv.register, lhs); |
| 2474 | try self.genSetReg(lhs_ty, lhs_mcv.register, lhs); |
| 2461 | 2475 | branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.lhs).?, lhs); |
| 2462 | 2476 | } |
| 2463 | 2477 | if (rhs_mcv == .register and !rhs_is_register) { |
| 2464 | | try self.genSetReg(ty, rhs_mcv.register, rhs); |
| 2478 | try self.genSetReg(lhs_ty, rhs_mcv.register, rhs); |
| 2465 | 2479 | branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.rhs).?, rhs); |
| 2466 | 2480 | } |
| 2467 | 2481 | |
| ... | ... | @@ -2469,9 +2483,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2469 | 2483 | // The signedness of the integer does not matter for the cmp instruction |
| 2470 | 2484 | try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined); |
| 2471 | 2485 | |
| 2472 | | break :result switch (ty.isSignedInt()) { |
| 2473 | | true => MCValue{ .compare_flags_signed = op }, |
| 2474 | | false => MCValue{ .compare_flags_unsigned = op }, |
| 2486 | break :result switch (signedness) { |
| 2487 | .signed => MCValue{ .compare_flags_signed = op }, |
| 2488 | .unsigned => MCValue{ .compare_flags_unsigned = op }, |
| 2475 | 2489 | }; |
| 2476 | 2490 | }; |
| 2477 | 2491 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |