authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-18 13:18:59+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-18 13:18:59+01:00
log8c233687b4b0fdad725bf81b204dde7ccba45f56
tree5974b7e548172ad118cf83fc703676aeb983aee7
parentaaa641feba8866ac38f2d06a8db2a24fa134e2f5

stage2: partially implement intcast on x86_64

* fix violating encoding invariant for memory encoding * enable some cast tests for x86_64 and arm

4 files changed, 51 insertions(+), 5 deletions(-)

src/arch/x86_64/CodeGen.zig+19-3
......@@ -877,10 +877,26 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
877877 if (info_a.signedness != info_b.signedness)
878878 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
879879
880 if (info_a.bits == info_b.bits)
881 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
880 const operand_abi_size = operand_ty.abiSize(self.target.*);
881 const dest_ty = self.air.typeOfIndex(inst);
882 const dest_abi_size = dest_ty.abiSize(self.target.*);
883 const dst_mcv: MCValue = blk: {
884 if (info_a.bits == info_b.bits) {
885 break :blk operand;
886 }
887 if (operand_abi_size > 8 or dest_abi_size > 8) {
888 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
889 }
890 const reg = switch (operand) {
891 .register => |src_reg| try self.register_manager.allocReg(inst, &.{src_reg}),
892 else => try self.register_manager.allocReg(inst, &.{}),
893 };
894 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
895 try self.genSetReg(dest_ty, reg, operand);
896 break :blk .{ .register = registerAlias(reg, @intCast(u32, dest_abi_size)) };
897 };
882898
883 return self.fail("TODO implement intCast for {}", .{self.target.cpu.arch});
899 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
884900}
885901
886902fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
src/arch/x86_64/Emit.zig+1-1
......@@ -1320,7 +1320,7 @@ const Memory = struct {
13201320 encoder.disp32(@bitCast(i32, mem_op.disp));
13211321 }
13221322 } else {
1323 if (mem_op.disp == 0) {
1323 if (mem_op.disp == 0 and dst != 5) {
13241324 encoder.modRm_indirectDisp0(src, dst);
13251325 } else if (immOpSize(mem_op.disp) == 8) {
13261326 encoder.modRm_indirectDisp8(src, dst);
test/behavior.zig+1-1
......@@ -18,6 +18,7 @@ test {
1818 _ = @import("behavior/bool.zig");
1919 _ = @import("behavior/align.zig");
2020 _ = @import("behavior/array.zig");
21 _ = @import("behavior/cast.zig");
2122
2223 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {
2324 // Tests that pass for stage1, llvm backend, C backend, wasm backend.
......@@ -36,7 +37,6 @@ test {
3637 _ = @import("behavior/bugs/4954.zig");
3738 _ = @import("behavior/byval_arg_var.zig");
3839 _ = @import("behavior/call.zig");
39 _ = @import("behavior/cast.zig");
4040 _ = @import("behavior/defer.zig");
4141 _ = @import("behavior/enum.zig");
4242 _ = @import("behavior/error.zig");
test/behavior/cast.zig+30
......@@ -5,6 +5,8 @@ const maxInt = std.math.maxInt;
55const builtin = @import("builtin");
66
77test "int to ptr cast" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
9
810 const x = @as(usize, 13);
911 const y = @intToPtr(*u8, x);
1012 const z = @ptrToInt(y);
......@@ -12,11 +14,15 @@ test "int to ptr cast" {
1214}
1315
1416test "integer literal to pointer cast" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
1519 const vga_mem = @intToPtr(*u16, 0xB8000);
1620 try expect(@ptrToInt(vga_mem) == 0xB8000);
1721}
1822
1923test "peer type resolution: ?T and T" {
24 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25
2026 try expect(peerTypeTAndOptionalT(true, false).? == 0);
2127 try expect(peerTypeTAndOptionalT(false, false).? == 3);
2228 comptime {
......@@ -33,6 +39,8 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
3339}
3440
3541test "resolve undefined with integer" {
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
43
3644 try testResolveUndefWithInt(true, 1234);
3745 comptime try testResolveUndefWithInt(true, 1234);
3846}
......@@ -88,6 +96,8 @@ test "comptime_int @intToFloat" {
8896}
8997
9098test "@floatToInt" {
99 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
100
91101 try testFloatToInts();
92102 comptime try testFloatToInts();
93103}
......@@ -107,6 +117,8 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
107117}
108118
109119test "implicitly cast indirect pointer to maybe-indirect pointer" {
120 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
121
110122 const S = struct {
111123 const Self = @This();
112124 x: u8,
......@@ -163,6 +175,8 @@ test "@floatCast comptime_int and comptime_float" {
163175}
164176
165177test "coerce undefined to optional" {
178 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
179
166180 try expect(MakeType(void).getNull() == null);
167181 try expect(MakeType(void).getNonNull() != null);
168182}
......@@ -180,6 +194,8 @@ fn MakeType(comptime T: type) type {
180194}
181195
182196test "implicit cast from *[N]T to [*c]T" {
197 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
198
183199 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
184200 var y: [*c]u16 = &x;
185201
......@@ -190,6 +206,8 @@ test "implicit cast from *[N]T to [*c]T" {
190206}
191207
192208test "*usize to *void" {
209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
210
193211 var i = @as(usize, 0);
194212 var v = @ptrCast(*void, &i);
195213 v.* = {};
......@@ -202,6 +220,8 @@ test "@intToEnum passed a comptime_int to an enum with one item" {
202220}
203221
204222test "@intCast to u0 and use the result" {
223 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
224
205225 const S = struct {
206226 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
207227 try expect((one << @intCast(u0, bigzero)) == 1);
......@@ -213,6 +233,8 @@ test "@intCast to u0 and use the result" {
213233}
214234
215235test "peer result null and comptime_int" {
236 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
237
216238 const S = struct {
217239 fn blah(n: i32) ?i32 {
218240 if (n == 0) {
......@@ -234,6 +256,8 @@ test "peer result null and comptime_int" {
234256}
235257
236258test "*const ?[*]const T to [*c]const [*c]const T" {
259 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
260
237261 var array = [_]u8{ 'o', 'k' };
238262 const opt_array_ptr: ?[*]const u8 = &array;
239263 const a: *const ?[*]const u8 = &opt_array_ptr;
......@@ -243,6 +267,8 @@ test "*const ?[*]const T to [*c]const [*c]const T" {
243267}
244268
245269test "array coersion to undefined at runtime" {
270 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
271
246272 @setRuntimeSafety(true);
247273
248274 // TODO implement @setRuntimeSafety in stage2
......@@ -270,6 +296,8 @@ fn implicitIntLitToOptional() void {
270296}
271297
272298test "return u8 coercing into ?u32 return type" {
299 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
300
273301 const S = struct {
274302 fn doTheTest() !void {
275303 try expect(foo(123).? == 123);
......@@ -288,6 +316,8 @@ test "cast from ?[*]T to ??[*]T" {
288316}
289317
290318test "peer type unsigned int to signed" {
319 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
320
291321 var w: u31 = 5;
292322 var x: u8 = 7;
293323 var y: i32 = -5;