authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-04-30 20:49:57+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-05-16 22:47:52+07:00
log662a61fcc3824deacba510e5b036be6feb941d2b
tree8620a6de914924b8d8156e0429ccd6eb15270350
parent5b03d55c5ecf697086db7c454e0f3982fec42408

stage2: sparc64: Implement airIsErr and airIsNonErr


3 files changed, 84 insertions(+), 2 deletions(-)

src/arch/sparc64/CodeGen.zig+82-2
......@@ -125,6 +125,12 @@ const MCValue = union(enum) {
125125 stack_offset: u32,
126126 /// The value is a pointer to one of the stack variables (payload is stack offset).
127127 ptr_stack_offset: u32,
128 /// The value is in the compare flags assuming an unsigned operation,
129 /// with this operator applied on top of it.
130 compare_flags_unsigned: math.CompareOperator,
131 /// The value is in the compare flags assuming a signed operation,
132 /// with this operator applied on top of it.
133 compare_flags_signed: math.CompareOperator,
128134
129135 fn isMemory(mcv: MCValue) bool {
130136 return switch (mcv) {
......@@ -536,9 +542,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
536542 .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),
537543 .is_null => @panic("TODO try self.airIsNull(inst)"),
538544 .is_null_ptr => @panic("TODO try self.airIsNullPtr(inst)"),
539 .is_non_err => @panic("TODO try self.airIsNonErr(inst)"),
545 .is_non_err => try self.airIsNonErr(inst),
540546 .is_non_err_ptr => @panic("TODO try self.airIsNonErrPtr(inst)"),
541 .is_err => @panic("TODO try self.airIsErr(inst)"),
547 .is_err => try self.airIsErr(inst),
542548 .is_err_ptr => @panic("TODO try self.airIsErrPtr(inst)"),
543549 .load => @panic("TODO try self.airLoad(inst)"),
544550 .loop => @panic("TODO try self.airLoop(inst)"),
......@@ -872,6 +878,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
872878 .unreach => unreachable,
873879 .dead => unreachable,
874880 .memory => unreachable,
881 .compare_flags_signed => unreachable,
882 .compare_flags_unsigned => unreachable,
875883 .register => |reg| {
876884 try self.register_manager.getReg(reg, null);
877885 try self.genSetReg(arg_ty, reg, arg_mcv);
......@@ -1004,6 +1012,26 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
10041012 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
10051013}
10061014
1015fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
1016 const un_op = self.air.instructions.items(.data)[inst].un_op;
1017 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1018 const operand = try self.resolveInst(un_op);
1019 const ty = self.air.typeOf(un_op);
1020 break :result try self.isErr(ty, operand);
1021 };
1022 return self.finishAir(inst, result, .{ un_op, .none, .none });
1023}
1024
1025fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
1026 const un_op = self.air.instructions.items(.data)[inst].un_op;
1027 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1028 const operand = try self.resolveInst(un_op);
1029 const ty = self.air.typeOf(un_op);
1030 break :result try self.isNonErr(ty, operand);
1031 };
1032 return self.finishAir(inst, result, .{ un_op, .none, .none });
1033}
1034
10071035fn airRet(self: *Self, inst: Air.Inst.Index) !void {
10081036 const un_op = self.air.instructions.items(.data)[inst].un_op;
10091037 const operand = try self.resolveInst(un_op);
......@@ -1259,6 +1287,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
12591287 switch (mcv) {
12601288 .dead => unreachable,
12611289 .unreach, .none => return, // Nothing to do.
1290 .compare_flags_signed => return self.fail("TODO: genSetReg for compare_flags_signed", .{}),
1291 .compare_flags_unsigned => return self.fail("TODO: genSetReg for compare_flags_unsigned", .{}),
12621292 .undef => {
12631293 if (!self.wantSafety())
12641294 return; // The already existing value will do just fine.
......@@ -1426,6 +1456,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
14261456 else => return self.fail("TODO implement memset", .{}),
14271457 }
14281458 },
1459 .compare_flags_unsigned,
1460 .compare_flags_signed,
14291461 .immediate,
14301462 .ptr_stack_offset,
14311463 => {
......@@ -1522,6 +1554,54 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
15221554 }
15231555}
15241556
1557fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
1558 const error_type = ty.errorUnionSet();
1559 const payload_type = ty.errorUnionPayload();
1560
1561 if (!error_type.hasRuntimeBits()) {
1562 return MCValue{ .immediate = 0 }; // always false
1563 } else if (!payload_type.hasRuntimeBits()) {
1564 if (error_type.abiSize(self.target.*) <= 8) {
1565 const reg_mcv: MCValue = switch (operand) {
1566 .register => operand,
1567 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
1568 };
1569
1570 _ = try self.addInst(.{
1571 .tag = .subcc,
1572 .data = .{ .arithmetic_3op = .{
1573 .is_imm = true,
1574 .rs1 = reg_mcv.register,
1575 .rs2_or_imm = .{ .imm = 0 },
1576 .rd = .g0,
1577 } },
1578 });
1579
1580 return MCValue{ .compare_flags_unsigned = .gt };
1581 } else {
1582 return self.fail("TODO isErr for errors with size > 8", .{});
1583 }
1584 } else {
1585 return self.fail("TODO isErr for non-empty payloads", .{});
1586 }
1587}
1588
1589fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
1590 // Call isErr, then negate the result.
1591 const is_err_result = try self.isErr(ty, operand);
1592 switch (is_err_result) {
1593 .compare_flags_unsigned => |op| {
1594 assert(op == .gt);
1595 return MCValue{ .compare_flags_unsigned = .lte };
1596 },
1597 .immediate => |imm| {
1598 assert(imm == 0);
1599 return MCValue{ .immediate = 1 };
1600 },
1601 else => unreachable,
1602 }
1603}
1604
15251605fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigTomb {
15261606 try self.ensureProcessDeathCapacity(operand_count + 1);
15271607 return BigTomb{
src/arch/sparc64/Emit.zig+1
......@@ -81,6 +81,7 @@ pub fn emitMir(
8181 .stx => try emit.mirArithmetic3Op(inst),
8282
8383 .sub => try emit.mirArithmetic3Op(inst),
84 .subcc => @panic("TODO implement sparcv9 subcc"),
8485
8586 .tcc => try emit.mirTrap(inst),
8687 }
src/arch/sparc64/Mir.zig+1
......@@ -106,6 +106,7 @@ pub const Inst = struct {
106106 /// This uses the arithmetic_3op field.
107107 // TODO add other operations.
108108 sub,
109 subcc,
109110
110111 /// A.61 Trap on Integer Condition Codes (Tcc)
111112 /// This uses the trap field.