stage2: partially implement intcast on x86_64

* fix violating encoding invariant for memory encoding
* enable some cast tests for x86_64 and arm
This commit is contained in:
Jakub Konka 2022-01-18 13:18:59 +01:00
parent aaa641feba
commit 8c233687b4
4 changed files with 51 additions and 5 deletions

View File

@ -877,10 +877,26 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
if (info_a.signedness != info_b.signedness)
return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
if (info_a.bits == info_b.bits)
return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
const operand_abi_size = operand_ty.abiSize(self.target.*);
const dest_ty = self.air.typeOfIndex(inst);
const dest_abi_size = dest_ty.abiSize(self.target.*);
const dst_mcv: MCValue = blk: {
if (info_a.bits == info_b.bits) {
break :blk operand;
}
if (operand_abi_size > 8 or dest_abi_size > 8) {
return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
}
const reg = switch (operand) {
.register => |src_reg| try self.register_manager.allocReg(inst, &.{src_reg}),
else => try self.register_manager.allocReg(inst, &.{}),
};
try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
try self.genSetReg(dest_ty, reg, operand);
break :blk .{ .register = registerAlias(reg, @intCast(u32, dest_abi_size)) };
};
return self.fail("TODO implement intCast for {}", .{self.target.cpu.arch});
return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
}
fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {

View File

@ -1320,7 +1320,7 @@ const Memory = struct {
encoder.disp32(@bitCast(i32, mem_op.disp));
}
} else {
if (mem_op.disp == 0) {
if (mem_op.disp == 0 and dst != 5) {
encoder.modRm_indirectDisp0(src, dst);
} else if (immOpSize(mem_op.disp) == 8) {
encoder.modRm_indirectDisp8(src, dst);

View File

@ -18,6 +18,7 @@ test {
_ = @import("behavior/bool.zig");
_ = @import("behavior/align.zig");
_ = @import("behavior/array.zig");
_ = @import("behavior/cast.zig");
if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {
// Tests that pass for stage1, llvm backend, C backend, wasm backend.
@ -36,7 +37,6 @@ test {
_ = @import("behavior/bugs/4954.zig");
_ = @import("behavior/byval_arg_var.zig");
_ = @import("behavior/call.zig");
_ = @import("behavior/cast.zig");
_ = @import("behavior/defer.zig");
_ = @import("behavior/enum.zig");
_ = @import("behavior/error.zig");

View File

@ -5,6 +5,8 @@ const maxInt = std.math.maxInt;
const builtin = @import("builtin");
test "int to ptr cast" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const x = @as(usize, 13);
const y = @intToPtr(*u8, x);
const z = @ptrToInt(y);
@ -12,11 +14,15 @@ test "int to ptr cast" {
}
test "integer literal to pointer cast" {
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
const vga_mem = @intToPtr(*u16, 0xB8000);
try expect(@ptrToInt(vga_mem) == 0xB8000);
}
test "peer type resolution: ?T and T" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
try expect(peerTypeTAndOptionalT(true, false).? == 0);
try expect(peerTypeTAndOptionalT(false, false).? == 3);
comptime {
@ -33,6 +39,8 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
}
test "resolve undefined with integer" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
try testResolveUndefWithInt(true, 1234);
comptime try testResolveUndefWithInt(true, 1234);
}
@ -88,6 +96,8 @@ test "comptime_int @intToFloat" {
}
test "@floatToInt" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
try testFloatToInts();
comptime try testFloatToInts();
}
@ -107,6 +117,8 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
}
test "implicitly cast indirect pointer to maybe-indirect pointer" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
const S = struct {
const Self = @This();
x: u8,
@ -163,6 +175,8 @@ test "@floatCast comptime_int and comptime_float" {
}
test "coerce undefined to optional" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
try expect(MakeType(void).getNull() == null);
try expect(MakeType(void).getNonNull() != null);
}
@ -180,6 +194,8 @@ fn MakeType(comptime T: type) type {
}
test "implicit cast from *[N]T to [*c]T" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
var y: [*c]u16 = &x;
@ -190,6 +206,8 @@ test "implicit cast from *[N]T to [*c]T" {
}
test "*usize to *void" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
var i = @as(usize, 0);
var v = @ptrCast(*void, &i);
v.* = {};
@ -202,6 +220,8 @@ test "@intToEnum passed a comptime_int to an enum with one item" {
}
test "@intCast to u0 and use the result" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
const S = struct {
fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
try expect((one << @intCast(u0, bigzero)) == 1);
@ -213,6 +233,8 @@ test "@intCast to u0 and use the result" {
}
test "peer result null and comptime_int" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
const S = struct {
fn blah(n: i32) ?i32 {
if (n == 0) {
@ -234,6 +256,8 @@ test "peer result null and comptime_int" {
}
test "*const ?[*]const T to [*c]const [*c]const T" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
var array = [_]u8{ 'o', 'k' };
const opt_array_ptr: ?[*]const u8 = &array;
const a: *const ?[*]const u8 = &opt_array_ptr;
@ -243,6 +267,8 @@ test "*const ?[*]const T to [*c]const [*c]const T" {
}
test "array coersion to undefined at runtime" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
@setRuntimeSafety(true);
// TODO implement @setRuntimeSafety in stage2
@ -270,6 +296,8 @@ fn implicitIntLitToOptional() void {
}
test "return u8 coercing into ?u32 return type" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
try expect(foo(123).? == 123);
@ -288,6 +316,8 @@ test "cast from ?[*]T to ??[*]T" {
}
test "peer type unsigned int to signed" {
if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
var w: u31 = 5;
var x: u8 = 7;
var y: i32 = -5;