diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index ab421c4d32..1db3f862ed 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -3236,7 +3236,10 @@ pub const epoll_event = switch (builtin.zig_backend) { }, else => extern struct { events: u32, - data: epoll_data align(4), + data: epoll_data align(switch (native_arch) { + .x86_64 => 4, + else => @alignOf(epoll_data), + }), }, }; diff --git a/lib/std/x/os/io.zig b/lib/std/x/os/io.zig index e61d212e52..35e7c3e1ed 100644 --- a/lib/std/x/os/io.zig +++ b/lib/std/x/os/io.zig @@ -117,7 +117,6 @@ pub const Reactor = struct { }; test "reactor/linux: drive async tcp client/listener pair" { - if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; if (native_os.tag != .linux) return error.SkipZigTest; const ip = std.x.net.ip; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 9dc20755eb..6ebbd2aaf8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2680,11 +2680,15 @@ pub const DeclGen = struct { comptime assert(struct_layout_version == 2); var offset: u64 = 0; var big_align: u32 = 0; + var any_underaligned_fields = false; for (struct_obj.fields.values()) |field| { if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue; const field_align = field.normalAlignment(target); + const field_ty_align = field.ty.abiAlignment(target); + any_underaligned_fields = any_underaligned_fields or + field_align < field_ty_align; big_align = @maximum(big_align, field_align); const prev_offset = offset; offset = std.mem.alignForwardGeneric(u64, offset, field_align); @@ -2712,7 +2716,7 @@ pub const DeclGen = struct { llvm_struct_ty.structSetBody( llvm_field_types.items.ptr, @intCast(c_uint, llvm_field_types.items.len), - .False, + llvm.Bool.fromBool(any_underaligned_fields), ); return llvm_struct_ty; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 709c73807b..22d09a066d 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1372,3 +1372,26 @@ test "struct field init value is size of the struct" { var s: namespace.S = .{ .blah = 1234 }; try expect(s.size == 4); } + +test "under-aligned struct field" { + if (builtin.zig_backend == .stage1) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const U = extern union { + fd: i32, + u32: u32, + u64: u64, + }; + const S = extern struct { + events: u32, + data: U align(4), + }; + var runtime: usize = 1234; + const ptr = &S{ .events = 0, .data = .{ .u64 = runtime } }; + const array = @ptrCast(*const [12]u8, ptr); + const result = std.mem.readIntNative(u64, array[4..12]); + try expect(result == 1234); +}