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 {...@@ -877,10 +877,26 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
877 if (info_a.signedness != info_b.signedness)877 if (info_a.signedness != info_b.signedness)
878 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});878 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
879879
880 if (info_a.bits == info_b.bits)880 const operand_abi_size = operand_ty.abiSize(self.target.*);
881 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });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 });
884}900}
885901
886fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {902fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
src/arch/x86_64/Emit.zig+1-1
...@@ -1320,7 +1320,7 @@ const Memory = struct {...@@ -1320,7 +1320,7 @@ const Memory = struct {
1320 encoder.disp32(@bitCast(i32, mem_op.disp));1320 encoder.disp32(@bitCast(i32, mem_op.disp));
1321 }1321 }
1322 } else {1322 } else {
1323 if (mem_op.disp == 0) {1323 if (mem_op.disp == 0 and dst != 5) {
1324 encoder.modRm_indirectDisp0(src, dst);1324 encoder.modRm_indirectDisp0(src, dst);
1325 } else if (immOpSize(mem_op.disp) == 8) {1325 } else if (immOpSize(mem_op.disp) == 8) {
1326 encoder.modRm_indirectDisp8(src, dst);1326 encoder.modRm_indirectDisp8(src, dst);
test/behavior.zig+1-1
...@@ -18,6 +18,7 @@ test {...@@ -18,6 +18,7 @@ test {
18 _ = @import("behavior/bool.zig");18 _ = @import("behavior/bool.zig");
19 _ = @import("behavior/align.zig");19 _ = @import("behavior/align.zig");
20 _ = @import("behavior/array.zig");20 _ = @import("behavior/array.zig");
21 _ = @import("behavior/cast.zig");
2122
22 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {23 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64) {
23 // Tests that pass for stage1, llvm backend, C backend, wasm backend.24 // Tests that pass for stage1, llvm backend, C backend, wasm backend.
...@@ -36,7 +37,6 @@ test {...@@ -36,7 +37,6 @@ test {
36 _ = @import("behavior/bugs/4954.zig");37 _ = @import("behavior/bugs/4954.zig");
37 _ = @import("behavior/byval_arg_var.zig");38 _ = @import("behavior/byval_arg_var.zig");
38 _ = @import("behavior/call.zig");39 _ = @import("behavior/call.zig");
39 _ = @import("behavior/cast.zig");
40 _ = @import("behavior/defer.zig");40 _ = @import("behavior/defer.zig");
41 _ = @import("behavior/enum.zig");41 _ = @import("behavior/enum.zig");
42 _ = @import("behavior/error.zig");42 _ = @import("behavior/error.zig");
test/behavior/cast.zig+30
...@@ -5,6 +5,8 @@ const maxInt = std.math.maxInt;...@@ -5,6 +5,8 @@ const maxInt = std.math.maxInt;
5const builtin = @import("builtin");5const builtin = @import("builtin");
66
7test "int to ptr cast" {7test "int to ptr cast" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
9
8 const x = @as(usize, 13);10 const x = @as(usize, 13);
9 const y = @intToPtr(*u8, x);11 const y = @intToPtr(*u8, x);
10 const z = @ptrToInt(y);12 const z = @ptrToInt(y);
...@@ -12,11 +14,15 @@ test "int to ptr cast" {...@@ -12,11 +14,15 @@ test "int to ptr cast" {
12}14}
1315
14test "integer literal to pointer cast" {16test "integer literal to pointer cast" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
15 const vga_mem = @intToPtr(*u16, 0xB8000);19 const vga_mem = @intToPtr(*u16, 0xB8000);
16 try expect(@ptrToInt(vga_mem) == 0xB8000);20 try expect(@ptrToInt(vga_mem) == 0xB8000);
17}21}
1822
19test "peer type resolution: ?T and T" {23test "peer type resolution: ?T and T" {
24 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25
20 try expect(peerTypeTAndOptionalT(true, false).? == 0);26 try expect(peerTypeTAndOptionalT(true, false).? == 0);
21 try expect(peerTypeTAndOptionalT(false, false).? == 3);27 try expect(peerTypeTAndOptionalT(false, false).? == 3);
22 comptime {28 comptime {
...@@ -33,6 +39,8 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {...@@ -33,6 +39,8 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
33}39}
3440
35test "resolve undefined with integer" {41test "resolve undefined with integer" {
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
43
36 try testResolveUndefWithInt(true, 1234);44 try testResolveUndefWithInt(true, 1234);
37 comptime try testResolveUndefWithInt(true, 1234);45 comptime try testResolveUndefWithInt(true, 1234);
38}46}
...@@ -88,6 +96,8 @@ test "comptime_int @intToFloat" {...@@ -88,6 +96,8 @@ test "comptime_int @intToFloat" {
88}96}
8997
90test "@floatToInt" {98test "@floatToInt" {
99 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
100
91 try testFloatToInts();101 try testFloatToInts();
92 comptime try testFloatToInts();102 comptime try testFloatToInts();
93}103}
...@@ -107,6 +117,8 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {...@@ -107,6 +117,8 @@ fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) !void {
107}117}
108118
109test "implicitly cast indirect pointer to maybe-indirect pointer" {119test "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
110 const S = struct {122 const S = struct {
111 const Self = @This();123 const Self = @This();
112 x: u8,124 x: u8,
...@@ -163,6 +175,8 @@ test "@floatCast comptime_int and comptime_float" {...@@ -163,6 +175,8 @@ test "@floatCast comptime_int and comptime_float" {
163}175}
164176
165test "coerce undefined to optional" {177test "coerce undefined to optional" {
178 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
179
166 try expect(MakeType(void).getNull() == null);180 try expect(MakeType(void).getNull() == null);
167 try expect(MakeType(void).getNonNull() != null);181 try expect(MakeType(void).getNonNull() != null);
168}182}
...@@ -180,6 +194,8 @@ fn MakeType(comptime T: type) type {...@@ -180,6 +194,8 @@ fn MakeType(comptime T: type) type {
180}194}
181195
182test "implicit cast from *[N]T to [*c]T" {196test "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
183 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };199 var x: [4]u16 = [4]u16{ 0, 1, 2, 3 };
184 var y: [*c]u16 = &x;200 var y: [*c]u16 = &x;
185201
...@@ -190,6 +206,8 @@ test "implicit cast from *[N]T to [*c]T" {...@@ -190,6 +206,8 @@ test "implicit cast from *[N]T to [*c]T" {
190}206}
191207
192test "*usize to *void" {208test "*usize to *void" {
209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
210
193 var i = @as(usize, 0);211 var i = @as(usize, 0);
194 var v = @ptrCast(*void, &i);212 var v = @ptrCast(*void, &i);
195 v.* = {};213 v.* = {};
...@@ -202,6 +220,8 @@ test "@intToEnum passed a comptime_int to an enum with one item" {...@@ -202,6 +220,8 @@ test "@intToEnum passed a comptime_int to an enum with one item" {
202}220}
203221
204test "@intCast to u0 and use the result" {222test "@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
205 const S = struct {225 const S = struct {
206 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {226 fn doTheTest(zero: u1, one: u1, bigzero: i32) !void {
207 try expect((one << @intCast(u0, bigzero)) == 1);227 try expect((one << @intCast(u0, bigzero)) == 1);
...@@ -213,6 +233,8 @@ test "@intCast to u0 and use the result" {...@@ -213,6 +233,8 @@ test "@intCast to u0 and use the result" {
213}233}
214234
215test "peer result null and comptime_int" {235test "peer result null and comptime_int" {
236 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
237
216 const S = struct {238 const S = struct {
217 fn blah(n: i32) ?i32 {239 fn blah(n: i32) ?i32 {
218 if (n == 0) {240 if (n == 0) {
...@@ -234,6 +256,8 @@ test "peer result null and comptime_int" {...@@ -234,6 +256,8 @@ test "peer result null and comptime_int" {
234}256}
235257
236test "*const ?[*]const T to [*c]const [*c]const T" {258test "*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
237 var array = [_]u8{ 'o', 'k' };261 var array = [_]u8{ 'o', 'k' };
238 const opt_array_ptr: ?[*]const u8 = &array;262 const opt_array_ptr: ?[*]const u8 = &array;
239 const a: *const ?[*]const u8 = &opt_array_ptr;263 const a: *const ?[*]const u8 = &opt_array_ptr;
...@@ -243,6 +267,8 @@ test "*const ?[*]const T to [*c]const [*c]const T" {...@@ -243,6 +267,8 @@ test "*const ?[*]const T to [*c]const [*c]const T" {
243}267}
244268
245test "array coersion to undefined at runtime" {269test "array coersion to undefined at runtime" {
270 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
271
246 @setRuntimeSafety(true);272 @setRuntimeSafety(true);
247273
248 // TODO implement @setRuntimeSafety in stage2274 // TODO implement @setRuntimeSafety in stage2
...@@ -270,6 +296,8 @@ fn implicitIntLitToOptional() void {...@@ -270,6 +296,8 @@ fn implicitIntLitToOptional() void {
270}296}
271297
272test "return u8 coercing into ?u32 return type" {298test "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
273 const S = struct {301 const S = struct {
274 fn doTheTest() !void {302 fn doTheTest() !void {
275 try expect(foo(123).? == 123);303 try expect(foo(123).? == 123);
...@@ -288,6 +316,8 @@ test "cast from ?[*]T to ??[*]T" {...@@ -288,6 +316,8 @@ test "cast from ?[*]T to ??[*]T" {
288}316}
289317
290test "peer type unsigned int to signed" {318test "peer type unsigned int to signed" {
319 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
320
291 var w: u31 = 5;321 var w: u31 = 5;
292 var x: u8 = 7;322 var x: u8 = 7;
293 var y: i32 = -5;323 var y: i32 = -5;