mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
stage2: sparc64: Implement airIsErr and airIsNonErr
This commit is contained in:
parent
5b03d55c5e
commit
662a61fcc3
@ -125,6 +125,12 @@ const MCValue = union(enum) {
|
||||
stack_offset: u32,
|
||||
/// The value is a pointer to one of the stack variables (payload is stack offset).
|
||||
ptr_stack_offset: u32,
|
||||
/// The value is in the compare flags assuming an unsigned operation,
|
||||
/// with this operator applied on top of it.
|
||||
compare_flags_unsigned: math.CompareOperator,
|
||||
/// The value is in the compare flags assuming a signed operation,
|
||||
/// with this operator applied on top of it.
|
||||
compare_flags_signed: math.CompareOperator,
|
||||
|
||||
fn isMemory(mcv: MCValue) bool {
|
||||
return switch (mcv) {
|
||||
@ -536,9 +542,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.is_non_null_ptr => @panic("TODO try self.airIsNonNullPtr(inst)"),
|
||||
.is_null => @panic("TODO try self.airIsNull(inst)"),
|
||||
.is_null_ptr => @panic("TODO try self.airIsNullPtr(inst)"),
|
||||
.is_non_err => @panic("TODO try self.airIsNonErr(inst)"),
|
||||
.is_non_err => try self.airIsNonErr(inst),
|
||||
.is_non_err_ptr => @panic("TODO try self.airIsNonErrPtr(inst)"),
|
||||
.is_err => @panic("TODO try self.airIsErr(inst)"),
|
||||
.is_err => try self.airIsErr(inst),
|
||||
.is_err_ptr => @panic("TODO try self.airIsErrPtr(inst)"),
|
||||
.load => @panic("TODO try self.airLoad(inst)"),
|
||||
.loop => @panic("TODO try self.airLoop(inst)"),
|
||||
@ -872,6 +878,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
|
||||
.unreach => unreachable,
|
||||
.dead => unreachable,
|
||||
.memory => unreachable,
|
||||
.compare_flags_signed => unreachable,
|
||||
.compare_flags_unsigned => unreachable,
|
||||
.register => |reg| {
|
||||
try self.register_manager.getReg(reg, null);
|
||||
try self.genSetReg(arg_ty, reg, arg_mcv);
|
||||
@ -1004,6 +1012,26 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||
const operand = try self.resolveInst(un_op);
|
||||
const ty = self.air.typeOf(un_op);
|
||||
break :result try self.isErr(ty, operand);
|
||||
};
|
||||
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
||||
}
|
||||
|
||||
fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||
const operand = try self.resolveInst(un_op);
|
||||
const ty = self.air.typeOf(un_op);
|
||||
break :result try self.isNonErr(ty, operand);
|
||||
};
|
||||
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
||||
}
|
||||
|
||||
fn airRet(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
const operand = try self.resolveInst(un_op);
|
||||
@ -1259,6 +1287,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
switch (mcv) {
|
||||
.dead => unreachable,
|
||||
.unreach, .none => return, // Nothing to do.
|
||||
.compare_flags_signed => return self.fail("TODO: genSetReg for compare_flags_signed", .{}),
|
||||
.compare_flags_unsigned => return self.fail("TODO: genSetReg for compare_flags_unsigned", .{}),
|
||||
.undef => {
|
||||
if (!self.wantSafety())
|
||||
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
|
||||
else => return self.fail("TODO implement memset", .{}),
|
||||
}
|
||||
},
|
||||
.compare_flags_unsigned,
|
||||
.compare_flags_signed,
|
||||
.immediate,
|
||||
.ptr_stack_offset,
|
||||
=> {
|
||||
@ -1522,6 +1554,54 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
|
||||
}
|
||||
}
|
||||
|
||||
fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
|
||||
const error_type = ty.errorUnionSet();
|
||||
const payload_type = ty.errorUnionPayload();
|
||||
|
||||
if (!error_type.hasRuntimeBits()) {
|
||||
return MCValue{ .immediate = 0 }; // always false
|
||||
} else if (!payload_type.hasRuntimeBits()) {
|
||||
if (error_type.abiSize(self.target.*) <= 8) {
|
||||
const reg_mcv: MCValue = switch (operand) {
|
||||
.register => operand,
|
||||
else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
|
||||
};
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .subcc,
|
||||
.data = .{ .arithmetic_3op = .{
|
||||
.is_imm = true,
|
||||
.rs1 = reg_mcv.register,
|
||||
.rs2_or_imm = .{ .imm = 0 },
|
||||
.rd = .g0,
|
||||
} },
|
||||
});
|
||||
|
||||
return MCValue{ .compare_flags_unsigned = .gt };
|
||||
} else {
|
||||
return self.fail("TODO isErr for errors with size > 8", .{});
|
||||
}
|
||||
} else {
|
||||
return self.fail("TODO isErr for non-empty payloads", .{});
|
||||
}
|
||||
}
|
||||
|
||||
fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
|
||||
// Call isErr, then negate the result.
|
||||
const is_err_result = try self.isErr(ty, operand);
|
||||
switch (is_err_result) {
|
||||
.compare_flags_unsigned => |op| {
|
||||
assert(op == .gt);
|
||||
return MCValue{ .compare_flags_unsigned = .lte };
|
||||
},
|
||||
.immediate => |imm| {
|
||||
assert(imm == 0);
|
||||
return MCValue{ .immediate = 1 };
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigTomb {
|
||||
try self.ensureProcessDeathCapacity(operand_count + 1);
|
||||
return BigTomb{
|
||||
|
||||
@ -81,6 +81,7 @@ pub fn emitMir(
|
||||
.stx => try emit.mirArithmetic3Op(inst),
|
||||
|
||||
.sub => try emit.mirArithmetic3Op(inst),
|
||||
.subcc => @panic("TODO implement sparcv9 subcc"),
|
||||
|
||||
.tcc => try emit.mirTrap(inst),
|
||||
}
|
||||
|
||||
@ -106,6 +106,7 @@ pub const Inst = struct {
|
||||
/// This uses the arithmetic_3op field.
|
||||
// TODO add other operations.
|
||||
sub,
|
||||
subcc,
|
||||
|
||||
/// A.61 Trap on Integer Condition Codes (Tcc)
|
||||
/// This uses the trap field.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user