authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-06-28 15:19:23-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-27 14:35:12-04:00
log897c0b35a92dba851edd2ce49314468d3e1fcaff
treed9a869dc8ce9331fdabec5b98595a420bd60e3a5
parentd01609af2aaf5a3c9ddd2ddf75a5d211e0e94b07

Revert "cbe: improve struct/union defs on 32-bit targets"

This reverts commit 5434f85c47f6412a8d5faf681419c15533bb388c, which was just hacking around other bugs.

2 files changed, 29 insertions(+), 61 deletions(-)

src/Type.zig+1-1
......@@ -962,7 +962,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
962962 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
963963 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));
964964 },
965 .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).defaultStructFieldAlignment(.auto, zcu),
965 .stage2_c, .stage2_wasm => return Type.fromInterned(vector_type.child).abiAlignment(zcu),
966966 .stage2_x86_64 => {
967967 if (vector_type.child == .bool_type) {
968968 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64";
src/codegen/c/type/render_defs.zig+28-60
......@@ -284,9 +284,8 @@ pub fn defineComplete(
284284 },
285285 },
286286 .array => if (ty.hasRuntimeBits(zcu)) {
287 const elem_ty = ty.childType(zcu);
288287 const name_cty: CType = .{ .arr = ty };
289 const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu);
288 const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu);
290289 const array_cty: CType = .{ .array = .{
291290 .len = ty.arrayLenIncludingSentinel(zcu),
292291 .elem_ty = &elem_cty,
......@@ -296,28 +295,17 @@ pub fn defineComplete(
296295 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);
297296 },
298297 } };
299 if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) {
300 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
301 name_cty.fmtTypeName(zcu),
302 array_cty.fmtDeclaratorPrefix(zcu),
303 array_cty.fmtDeclaratorSuffix(zcu),
304 ty.fmt(pt),
305 });
306 } else {
307 try w.print("zig_packed({f} {{ zig_under_align({d}) {f}array{f}; }}); /* {f} */\n", .{
308 name_cty.fmtTypeName(zcu),
309 elem_ty.abiAlignment(zcu).toByteUnits().?,
310 array_cty.fmtDeclaratorPrefix(zcu),
311 array_cty.fmtDeclaratorSuffix(zcu),
312 ty.fmt(pt),
313 });
314 }
298 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
299 name_cty.fmtTypeName(zcu),
300 array_cty.fmtDeclaratorPrefix(zcu),
301 array_cty.fmtDeclaratorSuffix(zcu),
302 ty.fmt(pt),
303 });
315304 try writeStaticAssertLayout(ty, name_cty, w, zcu);
316305 },
317306 .vector => if (ty.hasRuntimeBits(zcu)) {
318 const elem_ty = ty.childType(zcu);
319307 const name_cty: CType = .{ .vec = ty };
320 const elem_cty: CType = try .lower(elem_ty, deps, arena, zcu);
308 const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu);
321309 const array_cty: CType = .{ .array = .{
322310 .len = ty.arrayLenIncludingSentinel(zcu),
323311 .elem_ty = &elem_cty,
......@@ -363,39 +351,21 @@ fn defineTuple(
363351 const ip = &zcu.intern_pool;
364352 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;
365353
366 const tuple_align = ty.abiAlignment(zcu);
354 // Fields cannot be underaligned, because tuple fields cannot have specified alignments.
355 // However, overaligned fields are possible thanks to intermediate zero-bit fields.
367356
368 // If there are any underaligned fields, we need to byte-pack the tuple.
369 const pack: bool = pack: {
370 var offset: u64 = 0;
371 for (tuple.types.get(ip)) |field_ty_ip| {
372 const field_ty: Type = .fromInterned(field_ty_ip);
373 if (!field_ty.hasRuntimeBits(zcu)) continue;
374 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
375 const natural_offset = natural_align.forward(offset);
376 offset = field_ty.abiAlignment(zcu).forward(offset);
377 if (offset < natural_offset) break :pack true;
378 // Also pack if any field is more aligned than the tuple should be.
379 if (natural_align.compareStrict(.gt, tuple_align)) break :pack true;
380 offset += field_ty.abiSize(zcu);
381 }
382 break :pack false;
383 };
357 const tuple_align = ty.abiAlignment(zcu);
384358
385359 // If the alignment of other fields would not give the tuple sufficient alignment, we
386360 // need to align the first field (which does not affect its offset, because 0 is always
387361 // well-aligned) to indirectly specify the tuple alignment.
388 const overalign: bool = switch (pack) {
389 true => tuple_align.compareStrict(.gt, .@"1"),
390 false => for (tuple.types.get(ip)) |field_ty_ip| {
391 const field_ty: Type = .fromInterned(field_ty_ip);
392 if (!field_ty.hasRuntimeBits(zcu)) continue;
393 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
394 if (natural_align.compareStrict(.gte, tuple_align)) break false;
395 } else true,
396 };
362 const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| {
363 const field_ty: Type = .fromInterned(field_ty_ip);
364 if (!field_ty.hasRuntimeBits(zcu)) continue;
365 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
366 if (natural_align.compareStrict(.gte, tuple_align)) break false;
367 } else true;
397368
398 if (pack) try w.writeAll("zig_packed(");
399369 const name_cty: CType = .{ .@"struct" = ty };
400370 try w.print("{f} {{ /* {f} */\n", .{
401371 name_cty.fmtTypeName(zcu),
......@@ -406,18 +376,18 @@ fn defineTuple(
406376 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {
407377 if (field_val_ip != .none) continue; // `comptime` field
408378 const field_ty: Type = .fromInterned(field_ty_ip);
409 zig_offset = field_ty.abiAlignment(zcu).forward(zig_offset);
379 const field_align = field_ty.abiAlignment(zcu);
380 zig_offset = field_align.forward(zig_offset);
410381 if (!field_ty.hasRuntimeBits(zcu)) continue;
411 if (!pack) c_offset = field_ty.defaultStructFieldAlignment(.auto, zcu).forward(c_offset);
382 c_offset = field_align.forward(c_offset);
412383 try w.writeByte(' ');
413384 if (zig_offset == 0 and overalign) {
414385 // This is the first field; specify its alignment to align the tuple.
415386 try writeFieldAlign(field_ty, tuple_align, w, zcu);
416387 } else if (zig_offset > c_offset) {
417 // This field needs to be underaligned or overaligned compared to what its
418 // offset would otherwise be.
388 // This field needs to be overaligned compared to what its offset would otherwise be.
419389 const need_align: Alignment = .minStrict(
420 tuple_align, // don't make the tuple more aligned than it should be
390 tuple_align, // don't make the struct more aligned than it should be
421391 .fromLog2Units(@ctz(zig_offset)),
422392 );
423393 try writeFieldAlign(field_ty, need_align, w, zcu);
......@@ -433,9 +403,7 @@ fn defineTuple(
433403 zig_offset += field_size;
434404 c_offset += field_size;
435405 }
436 try w.writeByte('}');
437 if (pack) try w.writeByte(')');
438 try w.writeAll(";\n");
406 try w.writeAll("};\n");
439407
440408 try writeStaticAssertLayout(ty, name_cty, w, zcu);
441409}
......@@ -553,7 +521,7 @@ fn defineUnionAuto(
553521 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
554522 const field_ty: Type = .fromInterned(field_ty_ip);
555523 if (!field_ty.hasRuntimeBits(zcu)) continue;
556 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
524 const natural_align = field_ty.abiAlignment(zcu);
557525 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
558526 // The tag will immediately follow the payload. This layout may put the tag in what would
559527 // otherwise be padding on the payload union, because if the most-aligned union field is not
......@@ -571,7 +539,7 @@ fn defineUnionAuto(
571539 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
572540 const field_ty: Type = .fromInterned(field_ty_ip);
573541 if (!field_ty.hasRuntimeBits(zcu)) continue;
574 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
542 const natural_align = field_ty.abiAlignment(zcu);
575543 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
576544 } else overalign: {
577545 if (union_type.has_runtime_tag) {
......@@ -642,7 +610,7 @@ fn defineUnionExtern(
642610 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
643611 const field_ty: Type = .fromInterned(field_ty_ip);
644612 if (!field_ty.hasRuntimeBits(zcu)) continue;
645 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);
613 const natural_align = field_ty.abiAlignment(zcu);
646614 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
647615 } else false;
648616
......@@ -654,7 +622,7 @@ fn defineUnionExtern(
654622 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
655623 const field_ty: Type = .fromInterned(field_ty_ip);
656624 if (!field_ty.hasRuntimeBits(zcu)) continue;
657 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);
625 const natural_align = field_ty.abiAlignment(zcu);
658626 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
659627 } else overalign: {
660628 if (union_type.has_runtime_tag) {
......@@ -704,7 +672,7 @@ fn writeFieldAlign(
704672 w: *Writer,
705673 zcu: *const Zcu,
706674) Writer.Error!void {
707 if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) {
675 if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
708676 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
709677 } else {
710678 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});