mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 12:27:41 +00:00
x64: impl unwrap_errunion_payload and unwrap_errunion_err for register
This commit is contained in:
parent
a7ca40b281
commit
05431d7c4a
@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
const err_union_ty = self.air.typeOf(ty_op.operand);
|
||||
const err_ty = err_union_ty.errorUnionSet();
|
||||
const payload_ty = err_union_ty.errorUnionPayload();
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
operand.freezeIfRegister(&self.register_manager);
|
||||
defer operand.unfreezeIfRegister(&self.register_manager);
|
||||
|
||||
const result: MCValue = result: {
|
||||
if (!payload_ty.hasRuntimeBits()) break :result operand;
|
||||
switch (operand) {
|
||||
.stack_offset => |off| {
|
||||
break :result MCValue{ .stack_offset = off };
|
||||
},
|
||||
.register => {
|
||||
// TODO reuse operand
|
||||
break :result try self.copyToRegisterWithInstTracking(inst, err_ty, operand);
|
||||
},
|
||||
else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),
|
||||
}
|
||||
};
|
||||
@ -1763,13 +1771,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
|
||||
if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
|
||||
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
operand.freezeIfRegister(&self.register_manager);
|
||||
defer operand.unfreezeIfRegister(&self.register_manager);
|
||||
|
||||
const err_ty = err_union_ty.errorUnionSet();
|
||||
const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
|
||||
switch (operand) {
|
||||
.stack_offset => |off| {
|
||||
const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
|
||||
const offset = off - @intCast(i32, err_abi_size);
|
||||
break :result MCValue{ .stack_offset = offset };
|
||||
},
|
||||
.register => {
|
||||
// TODO reuse operand
|
||||
const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
|
||||
try self.shiftRegister(result.register.to64(), @intCast(u6, err_ty.bitSize(self.target.*)));
|
||||
break :result MCValue{
|
||||
.register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))),
|
||||
};
|
||||
},
|
||||
else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),
|
||||
}
|
||||
};
|
||||
@ -2686,27 +2705,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
|
||||
};
|
||||
|
||||
// Shift by struct_field_offset.
|
||||
const shift_amount = @intCast(u8, struct_field_offset * 8);
|
||||
if (shift_amount > 0) {
|
||||
if (shift_amount == 1) {
|
||||
_ = try self.addInst(.{
|
||||
.tag = .shr,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = dst_mcv.register,
|
||||
}).encode(),
|
||||
.data = undefined,
|
||||
});
|
||||
} else {
|
||||
_ = try self.addInst(.{
|
||||
.tag = .shr,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = dst_mcv.register,
|
||||
.flags = 0b10,
|
||||
}).encode(),
|
||||
.data = .{ .imm = shift_amount },
|
||||
});
|
||||
}
|
||||
}
|
||||
const shift = @intCast(u8, struct_field_offset * 8);
|
||||
try self.shiftRegister(dst_mcv.register, shift);
|
||||
|
||||
// Mask with reg.size() - struct_field_size
|
||||
const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*)));
|
||||
@ -5768,3 +5768,25 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
|
||||
unreachable; // TODO handle floating-point registers
|
||||
}
|
||||
}
|
||||
|
||||
fn shiftRegister(self: *Self, reg: Register, shift: u8) !void {
|
||||
if (shift == 0) return;
|
||||
if (shift == 1) {
|
||||
_ = try self.addInst(.{
|
||||
.tag = .shr,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = reg,
|
||||
}).encode(),
|
||||
.data = undefined,
|
||||
});
|
||||
} else {
|
||||
_ = try self.addInst(.{
|
||||
.tag = .shr,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = reg,
|
||||
.flags = 0b10,
|
||||
}).encode(),
|
||||
.data = .{ .imm = shift },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +78,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
|
||||
}
|
||||
|
||||
test "error return in assignment" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
@ -121,7 +120,6 @@ test "widen cast integer payload of error union function call" {
|
||||
}
|
||||
|
||||
test "debug info for optional error set" {
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
|
||||
@ -173,7 +171,6 @@ fn bar2() (error{}!void) {}
|
||||
test "error union type " {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try testErrorUnionType();
|
||||
@ -191,7 +188,6 @@ fn testErrorUnionType() !void {
|
||||
test "error set type" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
|
||||
try testErrorSetType();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user