mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
LLVM: fix lowering of structs with underaligned fields
When lowering a struct type to an LLVM struct type, keep track of whether there are any underaligned fields. If so, then make it a packed llvm struct. This works because we already insert manual padding bytes regardless. We could unconditionally use an LLVM packed struct; the reason we bother checking for underaligned fields is that it is a conservative choice, in case LLVM handles packed structs less optimally. A future improvement could simplify this code by unconditionally using packed LLVM structs and then make sure measure perf is unaffected. closes #12190
This commit is contained in:
parent
460211431f
commit
f550c29c4e
@ -3236,7 +3236,10 @@ pub const epoll_event = switch (builtin.zig_backend) {
|
|||||||
},
|
},
|
||||||
else => extern struct {
|
else => extern struct {
|
||||||
events: u32,
|
events: u32,
|
||||||
data: epoll_data align(4),
|
data: epoll_data align(switch (native_arch) {
|
||||||
|
.x86_64 => 4,
|
||||||
|
else => @alignOf(epoll_data),
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -117,7 +117,6 @@ pub const Reactor = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
test "reactor/linux: drive async tcp client/listener pair" {
|
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;
|
if (native_os.tag != .linux) return error.SkipZigTest;
|
||||||
|
|
||||||
const ip = std.x.net.ip;
|
const ip = std.x.net.ip;
|
||||||
|
|||||||
@ -2680,11 +2680,15 @@ pub const DeclGen = struct {
|
|||||||
comptime assert(struct_layout_version == 2);
|
comptime assert(struct_layout_version == 2);
|
||||||
var offset: u64 = 0;
|
var offset: u64 = 0;
|
||||||
var big_align: u32 = 0;
|
var big_align: u32 = 0;
|
||||||
|
var any_underaligned_fields = false;
|
||||||
|
|
||||||
for (struct_obj.fields.values()) |field| {
|
for (struct_obj.fields.values()) |field| {
|
||||||
if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
|
if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
|
||||||
|
|
||||||
const field_align = field.normalAlignment(target);
|
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);
|
big_align = @maximum(big_align, field_align);
|
||||||
const prev_offset = offset;
|
const prev_offset = offset;
|
||||||
offset = std.mem.alignForwardGeneric(u64, offset, field_align);
|
offset = std.mem.alignForwardGeneric(u64, offset, field_align);
|
||||||
@ -2712,7 +2716,7 @@ pub const DeclGen = struct {
|
|||||||
llvm_struct_ty.structSetBody(
|
llvm_struct_ty.structSetBody(
|
||||||
llvm_field_types.items.ptr,
|
llvm_field_types.items.ptr,
|
||||||
@intCast(c_uint, llvm_field_types.items.len),
|
@intCast(c_uint, llvm_field_types.items.len),
|
||||||
.False,
|
llvm.Bool.fromBool(any_underaligned_fields),
|
||||||
);
|
);
|
||||||
|
|
||||||
return llvm_struct_ty;
|
return llvm_struct_ty;
|
||||||
|
|||||||
@ -1372,3 +1372,26 @@ test "struct field init value is size of the struct" {
|
|||||||
var s: namespace.S = .{ .blah = 1234 };
|
var s: namespace.S = .{ .blah = 1234 };
|
||||||
try expect(s.size == 4);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user