aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-28 12:14:41 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-28 12:14:41 +0100
commita61ac9ecbf42a97a4f56f7384e5b862dcb169f4a (patch)
tree73413ea4f4ac89038dc2410d0c39cfe3f8ee9f85
parent57a823582cfb86a7c85c4598f5580325fb674ec4 (diff)
downloadzig-a61ac9ecbf42a97a4f56f7384e5b862dcb169f4a.tar.gz
zig-a61ac9ecbf42a97a4f56f7384e5b862dcb169f4a.zip
x64: fix store with ABI size > 8 on stack; pass union tests
-rw-r--r--src/arch/x86_64/CodeGen.zig11
-rw-r--r--test/behavior/union.zig64
2 files changed, 57 insertions, 18 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 6891df0a41..bf5ebf4d41 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -2484,8 +2484,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
});
},
.stack_offset => {
- const tmp_reg = try self.copyToTmpRegister(value_ty, value);
- return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
+ if (abi_size <= 8) {
+ const tmp_reg = try self.copyToTmpRegister(value_ty, value);
+ return self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
+ }
+
+ try self.genInlineMemcpy(0, value_ty, value, .{
+ .source_stack_base = .rbp,
+ .dest_stack_base = reg.to64(),
+ });
},
else => |other| {
return self.fail("TODO implement set pointee with {}", .{other});
diff --git a/test/behavior/union.zig b/test/behavior/union.zig
index 91bd783ce2..760eec53b2 100644
--- a/test/behavior/union.zig
+++ b/test/behavior/union.zig
@@ -4,70 +4,102 @@ const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const Tag = std.meta.Tag;
-const Foo = union {
+const FooWithFloats = union {
float: f64,
int: i32,
};
-test "basic unions" {
+test "basic unions with floats" {
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;
- var foo = Foo{ .int = 1 };
+ var foo = FooWithFloats{ .int = 1 };
try expect(foo.int == 1);
- foo = Foo{ .float = 12.34 };
+ foo = FooWithFloats{ .float = 12.34 };
try expect(foo.float == 12.34);
}
-test "init union with runtime value" {
+fn setFloat(foo: *FooWithFloats, x: f64) void {
+ foo.* = FooWithFloats{ .float = x };
+}
+
+test "init union with runtime value - floats" {
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;
- var foo: Foo = undefined;
+ var foo: FooWithFloats = undefined;
setFloat(&foo, 12.34);
try expect(foo.float == 12.34);
+}
+
+test "basic unions" {
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+
+ var foo = Foo{ .int = 1 };
+ try expect(foo.int == 1);
+ foo = Foo{ .str = .{ .slice = "Hello!" } };
+ try expect(std.mem.eql(u8, foo.str.slice, "Hello!"));
+}
+
+const Foo = union {
+ int: i32,
+ str: struct {
+ slice: []const u8,
+ },
+};
+
+test "init union with runtime value" {
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
+
+ var foo: Foo = undefined;
setInt(&foo, 42);
try expect(foo.int == 42);
-}
-fn setFloat(foo: *Foo, x: f64) void {
- foo.* = Foo{ .float = x };
+ setStr(&foo, "Hello!");
+ try expect(std.mem.eql(u8, foo.str.slice, "Hello!"));
}
fn setInt(foo: *Foo, x: i32) void {
foo.* = Foo{ .int = x };
}
+fn setStr(foo: *Foo, slice: []const u8) void {
+ foo.* = Foo{ .str = .{ .slice = slice } };
+}
+
test "comptime union field access" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
comptime {
- var foo = Foo{ .int = 0 };
+ var foo = FooWithFloats{ .int = 0 };
try expect(foo.int == 0);
- foo = Foo{ .float = 42.42 };
- try expect(foo.float == 42.42);
+ foo = FooWithFloats{ .float = 12.34 };
+ try expect(foo.float == 12.34);
}
}
const FooExtern = extern union {
- float: f64,
int: i32,
+ str: struct {
+ slice: []const u8,
+ },
};
test "basic extern unions" {
- 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;
var foo = FooExtern{ .int = 1 };
try expect(foo.int == 1);
- foo.float = 12.34;
- try expect(foo.float == 12.34);
+ foo.str.slice = "Well";
+ try expect(std.mem.eql(u8, foo.str.slice, "Well"));
}
const ExternPtrOrInt = extern union {