authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 12:14:41+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-28 12:14:41+01:00
loga61ac9ecbf42a97a4f56f7384e5b862dcb169f4a
tree73413ea4f4ac89038dc2410d0c39cfe3f8ee9f85
parent57a823582cfb86a7c85c4598f5580325fb674ec4

x64: fix store with ABI size > 8 on stack; pass union tests


2 files changed, 57 insertions(+), 18 deletions(-)

src/arch/x86_64/CodeGen.zig+9-2
...@@ -2484,8 +2484,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2484,8 +2484,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2484 });2484 });
2485 },2485 },
2486 .stack_offset => {2486 .stack_offset => {
2487 const tmp_reg = try self.copyToTmpRegister(value_ty, value);2487 if (abi_size <= 8) {
2488 return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);2488 const tmp_reg = try self.copyToTmpRegister(value_ty, value);
2489 return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
2490 }
2491
2492 try self.genInlineMemcpy(0, value_ty, value, .{
2493 .source_stack_base = .rbp,
2494 .dest_stack_base = reg.to64(),
2495 });
2489 },2496 },
2490 else => |other| {2497 else => |other| {
2491 return self.fail("TODO implement set pointee with {}", .{other});2498 return self.fail("TODO implement set pointee with {}", .{other});
test/behavior/union.zig+48-16
...@@ -4,70 +4,102 @@ const expect = std.testing.expect;...@@ -4,70 +4,102 @@ const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
5const Tag = std.meta.Tag;5const Tag = std.meta.Tag;
66
7const Foo = union {7const FooWithFloats = union {
8 float: f64,8 float: f64,
9 int: i32,9 int: i32,
10};10};
1111
12test "basic unions" {12test "basic unions with floats" {
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1616
17 var foo = Foo{ .int = 1 };17 var foo = FooWithFloats{ .int = 1 };
18 try expect(foo.int == 1);18 try expect(foo.int == 1);
19 foo = Foo{ .float = 12.34 };19 foo = FooWithFloats{ .float = 12.34 };
20 try expect(foo.float == 12.34);20 try expect(foo.float == 12.34);
21}21}
2222
23test "init union with runtime value" {23fn setFloat(foo: *FooWithFloats, x: f64) void {
24 foo.* = FooWithFloats{ .float = x };
25}
26
27test "init union with runtime value - floats" {
24 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;28 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2731
28 var foo: Foo = undefined;32 var foo: FooWithFloats = undefined;
2933
30 setFloat(&foo, 12.34);34 setFloat(&foo, 12.34);
31 try expect(foo.float == 12.34);35 try expect(foo.float == 12.34);
36}
37
38test "basic unions" {
39 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
41
42 var foo = Foo{ .int = 1 };
43 try expect(foo.int == 1);
44 foo = Foo{ .str = .{ .slice = "Hello!" } };
45 try expect(std.mem.eql(u8, foo.str.slice, "Hello!"));
46}
47
48const Foo = union {
49 int: i32,
50 str: struct {
51 slice: []const u8,
52 },
53};
54
55test "init union with runtime value" {
56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
57 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
58
59 var foo: Foo = undefined;
3260
33 setInt(&foo, 42);61 setInt(&foo, 42);
34 try expect(foo.int == 42);62 try expect(foo.int == 42);
35}
3663
37fn setFloat(foo: *Foo, x: f64) void {64 setStr(&foo, "Hello!");
38 foo.* = Foo{ .float = x };65 try expect(std.mem.eql(u8, foo.str.slice, "Hello!"));
39}66}
4067
41fn setInt(foo: *Foo, x: i32) void {68fn setInt(foo: *Foo, x: i32) void {
42 foo.* = Foo{ .int = x };69 foo.* = Foo{ .int = x };
43}70}
4471
72fn setStr(foo: *Foo, slice: []const u8) void {
73 foo.* = Foo{ .str = .{ .slice = slice } };
74}
75
45test "comptime union field access" {76test "comptime union field access" {
46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
4778
48 comptime {79 comptime {
49 var foo = Foo{ .int = 0 };80 var foo = FooWithFloats{ .int = 0 };
50 try expect(foo.int == 0);81 try expect(foo.int == 0);
5182
52 foo = Foo{ .float = 42.42 };83 foo = FooWithFloats{ .float = 12.34 };
53 try expect(foo.float == 42.42);84 try expect(foo.float == 12.34);
54 }85 }
55}86}
5687
57const FooExtern = extern union {88const FooExtern = extern union {
58 float: f64,
59 int: i32,89 int: i32,
90 str: struct {
91 slice: []const u8,
92 },
60};93};
6194
62test "basic extern unions" {95test "basic extern unions" {
63 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;96 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6698
67 var foo = FooExtern{ .int = 1 };99 var foo = FooExtern{ .int = 1 };
68 try expect(foo.int == 1);100 try expect(foo.int == 1);
69 foo.float = 12.34;101 foo.str.slice = "Well";
70 try expect(foo.float == 12.34);102 try expect(std.mem.eql(u8, foo.str.slice, "Well"));
71}103}
72104
73const ExternPtrOrInt = extern union {105const ExternPtrOrInt = extern union {