| ... | @@ -1099,15 +1099,22 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1099,15 +1099,22 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 1099 | | 1099 | |
| 1100 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { | 1100 | fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1101 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 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 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1110 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1104 | } | 1111 | } |
| 1105 | | 1112 | |
| 1106 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { | 1113 | fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1107 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1114 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1108 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1115 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1109 | const err_ty = self.air.typeOf(ty_op.operand); | 1116 | const error_union_ty = self.air.typeOf(ty_op.operand); |
| 1110 | const payload_ty = err_ty.errorUnionPayload(); | 1117 | const payload_ty = error_union_ty.errorUnionPayload(); |
| 1111 | if (!payload_ty.hasCodeGenBits()) break :result MCValue.none; | 1118 | if (!payload_ty.hasCodeGenBits()) break :result MCValue.none; |
| 1112 | | 1119 | |
| 1113 | return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{}); | 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,19 +2418,26 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2411 | | 2418 | |
| 2412 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | 2419 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2413 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 2420 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2414 | if (self.liveness.isUnused(inst)) | 2421 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2415 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 2422 | const lhs = try self.resolveInst(bin_op.lhs); |
| 2416 | const ty = self.air.typeOf(bin_op.lhs); | 2423 | const rhs = try self.resolveInst(bin_op.rhs); |
| 2417 | assert(ty.eql(self.air.typeOf(bin_op.rhs))); | 2424 | const lhs_ty = self.air.typeOf(bin_op.lhs); |
| 2418 | if (ty.zigTypeTag() == .ErrorSet) | | |
| 2419 | return self.fail("TODO implement cmp for errors", .{}); | | |
| 2420 | | 2425 | |
| 2421 | try self.spillCompareFlagsIfOccupied(); | 2426 | if (lhs_ty.abiSize(self.target.*) > 4) { |
| 2422 | self.compare_flags_inst = inst; | 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 | const lhs_is_register = lhs == .register; | 2441 | const lhs_is_register = lhs == .register; |
| 2428 | const rhs_is_register = rhs == .register; | 2442 | const rhs_is_register = rhs == .register; |
| 2429 | // lhs should always be a register | 2443 | // lhs should always be a register |
| ... | @@ -2457,11 +2471,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -2457,11 +2471,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2457 | // Move the operands to the newly allocated registers | 2471 | // Move the operands to the newly allocated registers |
| 2458 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 2472 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 2459 | if (lhs_mcv == .register and !lhs_is_register) { | 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 | branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.lhs).?, lhs); | 2475 | branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.lhs).?, lhs); |
| 2462 | } | 2476 | } |
| 2463 | if (rhs_mcv == .register and !rhs_is_register) { | 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 | branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.rhs).?, rhs); | 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,9 +2483,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2469 | // The signedness of the integer does not matter for the cmp instruction | 2483 | // The signedness of the integer does not matter for the cmp instruction |
| 2470 | try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined); | 2484 | try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined); |
| 2471 | | 2485 | |
| 2472 | break :result switch (ty.isSignedInt()) { | 2486 | break :result switch (signedness) { |
| 2473 | true => MCValue{ .compare_flags_signed = op }, | 2487 | .signed => MCValue{ .compare_flags_signed = op }, |
| 2474 | false => MCValue{ .compare_flags_unsigned = op }, | 2488 | .unsigned => MCValue{ .compare_flags_unsigned = op }, |
| 2475 | }; | 2489 | }; |
| 2476 | }; | 2490 | }; |
| 2477 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 2491 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |