authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-12-31 17:33:08+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-01-01 11:16:38+01:00
log845531dde10d215dc23956e2dc8a9a78125712a8
tree8c82bfcc788fa5dbc25a2931b1c65c7fcc0b81bd
parentf8163f7eaf45fa2b53a1f5ceac35088ad7d73e45
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: implement airUnwrapErrErr + airCmp for error sets


2 files changed, 62 insertions(+), 19 deletions(-)

src/arch/arm/CodeGen.zig+33-19
...@@ -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 {
10991099
1100fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {1100fn 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}
11051112
1106fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {1113fn 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;
11121119
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 {
24112418
2412fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {2419fn 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", .{});
24202425
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;
24232440
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 register2443 // 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 registers2471 // 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 }
24672481
...@@ -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 instruction2483 // 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);
24712485
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 });
test/stage2/arm.zig+29
...@@ -636,6 +636,35 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -636,6 +636,35 @@ pub fn addCases(ctx: *TestContext) !void {
636 ,636 ,
637 "Hello, World!\n",637 "Hello, World!\n",
638 );638 );
639
640 case.addCompareOutput(
641 \\pub fn main() void {
642 \\ foo() catch |err| {
643 \\ assert(err == error.Foo);
644 \\ assert(err != error.Bar);
645 \\ assert(err != error.Baz);
646 \\ };
647 \\ bar() catch |err| {
648 \\ assert(err != error.Foo);
649 \\ assert(err == error.Bar);
650 \\ assert(err != error.Baz);
651 \\ };
652 \\}
653 \\
654 \\fn assert(ok: bool) void {
655 \\ if (!ok) unreachable;
656 \\}
657 \\
658 \\fn foo() anyerror!void {
659 \\ return error.Foo;
660 \\}
661 \\
662 \\fn bar() anyerror!void {
663 \\ return error.Bar;
664 \\}
665 ,
666 "",
667 );
639 }668 }
640669
641 {670 {