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) {...@@ -125,6 +125,12 @@ const MCValue = union(enum) {
125 stack_offset: u32,125 stack_offset: u32,
126 /// The value is a pointer to one of the stack variables (payload is stack offset).126 /// The value is a pointer to one of the stack variables (payload is stack offset).
127 ptr_stack_offset: u32,127 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
129 fn isMemory(mcv: MCValue) bool {135 fn isMemory(mcv: MCValue) bool {
130 return switch (mcv) {136 return switch (mcv) {
...@@ -536,9 +542,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -536,9 +542,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
536 .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),542 .is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),
537 .is_null => @panic("TODO try self.airIsNull(inst)"),543 .is_null => @panic("TODO try self.airIsNull(inst)"),
538 .is_null_ptr => @panic("TODO try self.airIsNullPtr(inst)"),544 .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),
540 .is_non_err_ptr => @panic("TODO try self.airIsNonErrPtr(inst)"),546 .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),
542 .is_err_ptr => @panic("TODO try self.airIsErrPtr(inst)"),548 .is_err_ptr => @panic("TODO try self.airIsErrPtr(inst)"),
543 .load => @panic("TODO try self.airLoad(inst)"),549 .load => @panic("TODO try self.airLoad(inst)"),
544 .loop => @panic("TODO try self.airLoop(inst)"),550 .loop => @panic("TODO try self.airLoop(inst)"),
...@@ -872,6 +878,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -872,6 +878,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
872 .unreach => unreachable,878 .unreach => unreachable,
873 .dead => unreachable,879 .dead => unreachable,
874 .memory => unreachable,880 .memory => unreachable,
881 .compare_flags_signed => unreachable,
882 .compare_flags_unsigned => unreachable,
875 .register => |reg| {883 .register => |reg| {
876 try self.register_manager.getReg(reg, null);884 try self.register_manager.getReg(reg, null);
877 try self.genSetReg(arg_ty, reg, arg_mcv);885 try self.genSetReg(arg_ty, reg, arg_mcv);
...@@ -1004,6 +1012,26 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {...@@ -1004,6 +1012,26 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
1004 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1012 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1005}1013}
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
1007fn airRet(self: *Self, inst: Air.Inst.Index) !void {1035fn airRet(self: *Self, inst: Air.Inst.Index) !void {
1008 const un_op = self.air.instructions.items(.data)[inst].un_op;1036 const un_op = self.air.instructions.items(.data)[inst].un_op;
1009 const operand = try self.resolveInst(un_op);1037 const operand = try self.resolveInst(un_op);
...@@ -1259,6 +1287,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -1259,6 +1287,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
1259 switch (mcv) {1287 switch (mcv) {
1260 .dead => unreachable,1288 .dead => unreachable,
1261 .unreach, .none => return, // Nothing to do.1289 .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", .{}),
1262 .undef => {1292 .undef => {
1263 if (!self.wantSafety())1293 if (!self.wantSafety())
1264 return; // The already existing value will do just fine.1294 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...@@ -1426,6 +1456,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
1426 else => return self.fail("TODO implement memset", .{}),1456 else => return self.fail("TODO implement memset", .{}),
1427 }1457 }
1428 },1458 },
1459 .compare_flags_unsigned,
1460 .compare_flags_signed,
1429 .immediate,1461 .immediate,
1430 .ptr_stack_offset,1462 .ptr_stack_offset,
1431 => {1463 => {
...@@ -1522,6 +1554,54 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -1522,6 +1554,54 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
1522 }1554 }
1523}1555}
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
1525fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigTomb {1605fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigTomb {
1526 try self.ensureProcessDeathCapacity(operand_count + 1);1606 try self.ensureProcessDeathCapacity(operand_count + 1);
1527 return BigTomb{1607 return BigTomb{
src/arch/sparc64/Emit.zig+1
...@@ -81,6 +81,7 @@ pub fn emitMir(...@@ -81,6 +81,7 @@ pub fn emitMir(
81 .stx => try emit.mirArithmetic3Op(inst),81 .stx => try emit.mirArithmetic3Op(inst),
8282
83 .sub => try emit.mirArithmetic3Op(inst),83 .sub => try emit.mirArithmetic3Op(inst),
84 .subcc => @panic("TODO implement sparcv9 subcc"),
8485
85 .tcc => try emit.mirTrap(inst),86 .tcc => try emit.mirTrap(inst),
86 }87 }
src/arch/sparc64/Mir.zig+1
...@@ -106,6 +106,7 @@ pub const Inst = struct {...@@ -106,6 +106,7 @@ pub const Inst = struct {
106 /// This uses the arithmetic_3op field.106 /// This uses the arithmetic_3op field.
107 // TODO add other operations.107 // TODO add other operations.
108 sub,108 sub,
109 subcc,
109110
110 /// A.61 Trap on Integer Condition Codes (Tcc)111 /// A.61 Trap on Integer Condition Codes (Tcc)
111 /// This uses the trap field.112 /// This uses the trap field.