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 {
10991099
11001100fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
11011101 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 };
11031110 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
11041111}
11051112
11061113fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
11071114 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
11081115 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();
11111118 if (!payload_ty.hasCodeGenBits()) break :result MCValue.none;
11121119
11131120 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 {
24112418
24122419fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24132420 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);
24202425
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;
24232440
2424 const lhs = try self.resolveInst(bin_op.lhs);
2425 const rhs = try self.resolveInst(bin_op.rhs);
2426 const result: MCValue = result: {
24272441 const lhs_is_register = lhs == .register;
24282442 const rhs_is_register = rhs == .register;
24292443 // lhs should always be a register
......@@ -2457,11 +2471,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24572471 // Move the operands to the newly allocated registers
24582472 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
24592473 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);
24612475 branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.lhs).?, lhs);
24622476 }
24632477 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);
24652479 branch.inst_table.putAssumeCapacity(Air.refToIndex(bin_op.rhs).?, rhs);
24662480 }
24672481
......@@ -2469,9 +2483,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24692483 // The signedness of the integer does not matter for the cmp instruction
24702484 try self.genArmBinOpCode(undefined, lhs_mcv, rhs_mcv, false, .cmp_eq, undefined);
24712485
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 },
24752489 };
24762490 };
24772491 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 {
636636 ,
637637 "Hello, World!\n",
638638 );
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 );
639668 }
640669
641670 {