From 5a41bc1afd3e5b026baed74e7f075da8d23aa658 Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Sat, 3 Aug 2019 20:07:09 +0200 Subject: [PATCH 1/7] make >= 128-bit integer types 16-byte aligned --- src/analyze.cpp | 8 +++++++- test/stage1/behavior/align.zig | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 0af1baec35b7..3b6f6932c465 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5627,6 +5627,13 @@ ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { entry->llvm_type = LLVMIntType(size_in_bits); entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type); + if (size_in_bits >= 128) { + // Override the alignment reported by LLVM like Clang does. + // On x86_64 there are some instructions like CMPXCHG16B which require this. + // See: https://github.com/ziglang/zig/issues/2987 + assert(entry->abi_align == 8); + entry->abi_align = 16; + } } const char u_or_i = is_signed ? 'i' : 'u'; @@ -7267,7 +7274,6 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) { assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); assert(type->abi_size == 0 || type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); - assert(type->abi_align == 0 || type->abi_align == LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type)); return type->llvm_type; } diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index b64f45bb6b2b..56057972d1c3 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -220,6 +220,20 @@ test "alignment of structs" { }) == @alignOf(usize)); } +test "alignment of 128-bit integer type" { + expect(@alignOf(u128) == 16); +} + +test "alignment of struct with 128-bit field" { + expect(@alignOf(struct { x: u128}) == 16); +} + +test "comptime alignment of struct with 128-bit field" { + comptime { + expect(@alignOf(struct { x: u128}) == 16); + } +} + test "alignment of extern() void" { var runtime_nothing = nothing; const casted1 = @ptrCast(*const u8, runtime_nothing); From eeec6c4ad8094d803b9b71742883521258ea92b8 Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Sun, 4 Aug 2019 21:59:33 +0200 Subject: [PATCH 2/7] remove assertion for same type sizes as LLVM Types can have differnt sizes than LLVM would give them. Added test demonstrates this and would trip said assert. --- src/analyze.cpp | 1 - test/stage1/behavior/align.zig | 20 +++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 3b6f6932c465..983135bbcc02 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -7273,7 +7273,6 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) { assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); - assert(type->abi_size == 0 || type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); return type->llvm_type; } diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index 56057972d1c3..1cb15a2ae492 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -220,20 +220,30 @@ test "alignment of structs" { }) == @alignOf(usize)); } -test "alignment of 128-bit integer type" { +test "alignment of >= 128-bit integer type" { expect(@alignOf(u128) == 16); + expect(@alignOf(u129) == 16); } test "alignment of struct with 128-bit field" { - expect(@alignOf(struct { x: u128}) == 16); -} + expect(@alignOf(struct { + x: u128, + }) == 16); -test "comptime alignment of struct with 128-bit field" { comptime { - expect(@alignOf(struct { x: u128}) == 16); + expect(@alignOf(struct { + x: u128, + }) == 16); } } +test "size of struct with non-standard-LLVM alignment" { + expect(@sizeOf(struct { + x: u129, + y: u129, + }) == 64); +} + test "alignment of extern() void" { var runtime_nothing = nothing; const casted1 = @ptrCast(*const u8, runtime_nothing); From 6655117b0d568fc37320f35598c5d971ed5f0648 Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Sun, 4 Aug 2019 22:08:56 +0200 Subject: [PATCH 3/7] add hack to fix std.Mutex test --- std/mutex.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/mutex.zig b/std/mutex.zig index 5f3b9272d932..4236940dbee8 100644 --- a/std/mutex.zig +++ b/std/mutex.zig @@ -122,7 +122,7 @@ else switch (builtin.os) { }, }; -const TestContext = struct { +const TestContext = packed struct { mutex: *Mutex, data: i128, From 0166f72f8b7cced667ea80f49e8ab0a5fd28cc8a Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Tue, 6 Aug 2019 18:53:33 +0200 Subject: [PATCH 4/7] Revert "add hack to fix std.Mutex test" This reverts commit 6655117b0d568fc37320f35598c5d971ed5f0648. --- std/mutex.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/mutex.zig b/std/mutex.zig index 4236940dbee8..5f3b9272d932 100644 --- a/std/mutex.zig +++ b/std/mutex.zig @@ -122,7 +122,7 @@ else switch (builtin.os) { }, }; -const TestContext = packed struct { +const TestContext = struct { mutex: *Mutex, data: i128, From cd2a07f5536793dfb967c2ad1a6618fb5f4f9840 Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Tue, 6 Aug 2019 19:46:10 +0200 Subject: [PATCH 5/7] fix test based on review --- test/stage1/behavior/align.zig | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index 1cb15a2ae492..9fbcd35400c5 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -237,11 +237,18 @@ test "alignment of struct with 128-bit field" { } } -test "size of struct with non-standard-LLVM alignment" { - expect(@sizeOf(struct { - x: u129, - y: u129, - }) == 64); +test "size of extern struct with 128-bit field" { + expect(@sizeOf(extern struct { + x: u128, + y: u8, + }) == 32); + + comptime { + expect(@sizeOf(extern struct { + x: u128, + y: u8, + }) == 32); + } } test "alignment of extern() void" { From 958d2a8ee333c12f63d7aa2e335f36fa1a34c85c Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Tue, 6 Aug 2019 19:46:56 +0200 Subject: [PATCH 6/7] add tests which segfault --- test/stage1/behavior/align.zig | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index 9fbcd35400c5..87f0143554af 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -167,6 +167,14 @@ test "@ptrCast preserves alignment of bigger source" { expect(@typeOf(ptr) == *align(16) u8); } +fn give() anyerror!u128 { + return 3; +} + +test "return error union with 128-bit integer" { + expect(3 == try give()); +} + test "runtime known array index has best alignment possible" { // take full advantage of over-alignment var array align(4) = [_]u8{ 1, 2, 3, 4 }; @@ -251,6 +259,29 @@ test "size of extern struct with 128-bit field" { } } +const DefaultAligned = struct { + nevermind: u32, + badguy: i128, +}; + +test "read 128-bit field from default aligned struct in stack memory" { + var default_aligned = DefaultAligned { + .nevermind = 1, + .badguy = 12, + }; + expect(12 == default_aligned.badguy); +} + +var default_aligned_global = DefaultAligned { + .nevermind = 1, + .badguy = 12, +}; + +test "read 128-bit field from default aligned struct in global memory" { + + expect(12 == default_aligned_global.badguy); +} + test "alignment of extern() void" { var runtime_nothing = nothing; const casted1 = @ptrCast(*const u8, runtime_nothing); From 9b8fbbf3fd518d1c6bdc73cc50f4573e5f418d92 Mon Sep 17 00:00:00 2001 From: Martin Schwaighofer Date: Sat, 10 Aug 2019 12:07:15 +0200 Subject: [PATCH 7/7] add more assertions about struct alignment to tests --- test/stage1/behavior/align.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index 87f0143554af..9ea00fb32df2 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -269,6 +269,7 @@ test "read 128-bit field from default aligned struct in stack memory" { .nevermind = 1, .badguy = 12, }; + expect((@ptrToInt(&default_aligned.badguy) % 16) == 0); expect(12 == default_aligned.badguy); } @@ -278,7 +279,7 @@ var default_aligned_global = DefaultAligned { }; test "read 128-bit field from default aligned struct in global memory" { - + expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0); expect(12 == default_aligned_global.badguy); }