Skip to content

Commit 80170d0

Browse files
jacobly0andrewrk
authored andcommitted
Legalize: handle packed semantics
Closes #22915
1 parent 597dd32 commit 80170d0

File tree

9 files changed

+1249
-253
lines changed

9 files changed

+1249
-253
lines changed

src/Air/Legalize.zig

Lines changed: 1200 additions & 228 deletions
Large diffs are not rendered by default.

src/Type.zig

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,14 +1636,22 @@ pub fn bitSizeInner(
16361636
.array_type => |array_type| {
16371637
const len = array_type.lenIncludingSentinel();
16381638
if (len == 0) return 0;
1639-
const elem_ty = Type.fromInterned(array_type.child);
1640-
const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar;
1641-
if (elem_size == 0) return 0;
1642-
const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid);
1643-
return (len - 1) * 8 * elem_size + elem_bit_size;
1639+
const elem_ty: Type = .fromInterned(array_type.child);
1640+
switch (zcu.comp.getZigBackend()) {
1641+
else => {
1642+
const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar;
1643+
if (elem_size == 0) return 0;
1644+
const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid);
1645+
return (len - 1) * 8 * elem_size + elem_bit_size;
1646+
},
1647+
.stage2_x86_64 => {
1648+
const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid);
1649+
return elem_bit_size * len;
1650+
},
1651+
}
16441652
},
16451653
.vector_type => |vector_type| {
1646-
const child_ty = Type.fromInterned(vector_type.child);
1654+
const child_ty: Type = .fromInterned(vector_type.child);
16471655
const elem_bit_size = try child_ty.bitSizeInner(strat, zcu, tid);
16481656
return elem_bit_size * vector_type.len;
16491657
},
@@ -3549,10 +3557,16 @@ pub fn packedStructFieldPtrInfo(struct_ty: Type, parent_ptr_ty: Type, field_idx:
35493557
running_bits += @intCast(f_ty.bitSize(zcu));
35503558
}
35513559

3552-
const res_host_size: u16, const res_bit_offset: u16 = if (parent_ptr_info.packed_offset.host_size != 0)
3553-
.{ parent_ptr_info.packed_offset.host_size, parent_ptr_info.packed_offset.bit_offset + bit_offset }
3554-
else
3555-
.{ (running_bits + 7) / 8, bit_offset };
3560+
const res_host_size: u16, const res_bit_offset: u16 = if (parent_ptr_info.packed_offset.host_size != 0) .{
3561+
parent_ptr_info.packed_offset.host_size,
3562+
parent_ptr_info.packed_offset.bit_offset + bit_offset,
3563+
} else .{
3564+
switch (zcu.comp.getZigBackend()) {
3565+
else => (running_bits + 7) / 8,
3566+
.stage2_x86_64 => @intCast(struct_ty.abiSize(zcu)),
3567+
},
3568+
bit_offset,
3569+
};
35563570

35573571
// If the field happens to be byte-aligned, simplify the pointer type.
35583572
// We can only do this if the pointee's bit size matches its ABI byte size,

src/arch/x86_64/CodeGen.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features
6767
.scalarize_shl_sat = true,
6868
.scalarize_xor = use_old,
6969
.scalarize_not = use_old,
70+
.scalarize_bitcast = true,
7071
.scalarize_clz = use_old,
7172
.scalarize_ctz = true,
7273
.scalarize_popcount = true,
@@ -99,10 +100,16 @@ pub fn legalizeFeatures(target: *const std.Target) *const Air.Legalize.Features
99100

100101
.unsplat_shift_rhs = false,
101102
.reduce_one_elem_to_bitcast = true,
103+
102104
.expand_intcast_safe = true,
103105
.expand_add_safe = true,
104106
.expand_sub_safe = true,
105107
.expand_mul_safe = true,
108+
109+
.expand_packed_load = true,
110+
.expand_packed_store = true,
111+
.expand_packed_struct_field_val = true,
112+
.expand_packed_aggregate_init = true,
106113
}),
107114
};
108115
}

test/behavior.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ test {
117117

118118
_ = @import("behavior/x86_64.zig");
119119

120-
if (builtin.zig_backend != .stage2_spirv64 and builtin.cpu.arch == .wasm32) {
120+
if (builtin.cpu.arch == .wasm32) {
121121
_ = @import("behavior/wasm.zig");
122122
}
123123

test/behavior/align.zig

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,10 @@ test "sub-aligned pointer field access" {
528528
}
529529

530530
test "alignment of zero-bit types is respected" {
531-
if (true) return error.SkipZigTest; // TODO
531+
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
532+
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
533+
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
534+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
532535

533536
const S = struct { arr: [0]usize = .{} };
534537

@@ -598,11 +601,8 @@ test "function pointer @intFromPtr/@ptrFromInt roundtrip" {
598601
}
599602

600603
test "function pointer align mask" {
601-
if (!(builtin.cpu.arch.isArm() or builtin.cpu.arch.isMIPS())) return error.SkipZigTest;
602-
603-
const a: *const fn () callconv(.c) void = @ptrFromInt(0x20202021);
604-
_ = &a;
605-
606-
const b: *align(16) const fn () callconv(.c) void = @alignCast(a);
607-
_ = &b;
604+
const int = if (builtin.cpu.arch.isArm() or builtin.cpu.arch.isMIPS()) 0x20202021 else 0x20202020;
605+
const unaligned: *const fn () callconv(.c) void = @ptrFromInt(int);
606+
const aligned: *align(16) const fn () callconv(.c) void = @alignCast(unaligned);
607+
try expect(@intFromPtr(aligned) == int);
608608
}

test/behavior/bitcast.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,8 @@ test "comptime @bitCast packed struct to int and back" {
341341
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
342342
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
343343
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
344-
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
345344
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
345+
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
346346

347347
const S = packed struct {
348348
void: void = {},

test/behavior/cast.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2610,7 +2610,6 @@ test "@intFromBool on vector" {
26102610
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
26112611
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26122612
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2613-
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
26142613

26152614
const S = struct {
26162615
fn doTheTest() !void {

test/behavior/struct.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,9 @@ test "packed struct with non-ABI-aligned field" {
559559
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
560560
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
561561
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
562-
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
563562
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
564563
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
564+
if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
565565

566566
const S = packed struct {
567567
x: u9,

test/behavior/union.zig

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,9 +1607,13 @@ test "packed union field pointer has correct alignment" {
16071607
const bp = &b.u.x;
16081608
const cp = &c.u.x;
16091609

1610-
comptime assert(@TypeOf(ap) == *align(4:2:3) u20);
1611-
comptime assert(@TypeOf(bp) == *align(1:2:3) u20);
1612-
comptime assert(@TypeOf(cp) == *align(64:2:3) u20);
1610+
const host_size = switch (builtin.zig_backend) {
1611+
else => comptime std.math.divCeil(comptime_int, @bitSizeOf(S), 8) catch unreachable,
1612+
.stage2_x86_64 => @sizeOf(S),
1613+
};
1614+
comptime assert(@TypeOf(ap) == *align(4:2:host_size) u20);
1615+
comptime assert(@TypeOf(bp) == *align(1:2:host_size) u20);
1616+
comptime assert(@TypeOf(cp) == *align(64:2:host_size) u20);
16131617

16141618
a.u = .{ .x = 123 };
16151619
b.u = .{ .x = 456 };

0 commit comments

Comments
 (0)