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 {...@@ -962,7 +962,7 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
962 const bytes = ((elem_bits * vector_type.len) + 7) / 8;962 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
963 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));963 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));
964 },964 },
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),
966 .stage2_x86_64 => {966 .stage2_x86_64 => {
967 if (vector_type.child == .bool_type) {967 if (vector_type.child == .bool_type) {
968 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64";968 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(...@@ -284,9 +284,8 @@ pub fn defineComplete(
284 },284 },
285 },285 },
286 .array => if (ty.hasRuntimeBits(zcu)) {286 .array => if (ty.hasRuntimeBits(zcu)) {
287 const elem_ty = ty.childType(zcu);
288 const name_cty: CType = .{ .arr = ty };287 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);
290 const array_cty: CType = .{ .array = .{289 const array_cty: CType = .{ .array = .{
291 .len = ty.arrayLenIncludingSentinel(zcu),290 .len = ty.arrayLenIncludingSentinel(zcu),
292 .elem_ty = &elem_cty,291 .elem_ty = &elem_cty,
...@@ -296,28 +295,17 @@ pub fn defineComplete(...@@ -296,28 +295,17 @@ pub fn defineComplete(
296 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);295 break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu);
297 },296 },
298 } };297 } };
299 if (elem_ty.defaultStructFieldAlignment(.auto, zcu) == elem_ty.abiAlignment(zcu)) {298 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{
300 try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{299 name_cty.fmtTypeName(zcu),
301 name_cty.fmtTypeName(zcu),300 array_cty.fmtDeclaratorPrefix(zcu),
302 array_cty.fmtDeclaratorPrefix(zcu),301 array_cty.fmtDeclaratorSuffix(zcu),
303 array_cty.fmtDeclaratorSuffix(zcu),302 ty.fmt(pt),
304 ty.fmt(pt),303 });
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 }
315 try writeStaticAssertLayout(ty, name_cty, w, zcu);304 try writeStaticAssertLayout(ty, name_cty, w, zcu);
316 },305 },
317 .vector => if (ty.hasRuntimeBits(zcu)) {306 .vector => if (ty.hasRuntimeBits(zcu)) {
318 const elem_ty = ty.childType(zcu);
319 const name_cty: CType = .{ .vec = ty };307 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);
321 const array_cty: CType = .{ .array = .{309 const array_cty: CType = .{ .array = .{
322 .len = ty.arrayLenIncludingSentinel(zcu),310 .len = ty.arrayLenIncludingSentinel(zcu),
323 .elem_ty = &elem_cty,311 .elem_ty = &elem_cty,
...@@ -363,39 +351,21 @@ fn defineTuple(...@@ -363,39 +351,21 @@ fn defineTuple(
363 const ip = &zcu.intern_pool;351 const ip = &zcu.intern_pool;
364 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;352 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.357 const tuple_align = ty.abiAlignment(zcu);
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 };
384358
385 // If the alignment of other fields would not give the tuple sufficient alignment, we359 // If the alignment of other fields would not give the tuple sufficient alignment, we
386 // need to align the first field (which does not affect its offset, because 0 is always360 // need to align the first field (which does not affect its offset, because 0 is always
387 // well-aligned) to indirectly specify the tuple alignment.361 // well-aligned) to indirectly specify the tuple alignment.
388 const overalign: bool = switch (pack) {362 const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| {
389 true => tuple_align.compareStrict(.gt, .@"1"),363 const field_ty: Type = .fromInterned(field_ty_ip);
390 false => for (tuple.types.get(ip)) |field_ty_ip| {364 if (!field_ty.hasRuntimeBits(zcu)) continue;
391 const field_ty: Type = .fromInterned(field_ty_ip);365 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);
392 if (!field_ty.hasRuntimeBits(zcu)) continue;366 if (natural_align.compareStrict(.gte, tuple_align)) break false;
393 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);367 } else true;
394 if (natural_align.compareStrict(.gte, tuple_align)) break false;
395 } else true,
396 };
397368
398 if (pack) try w.writeAll("zig_packed(");
399 const name_cty: CType = .{ .@"struct" = ty };369 const name_cty: CType = .{ .@"struct" = ty };
400 try w.print("{f} {{ /* {f} */\n", .{370 try w.print("{f} {{ /* {f} */\n", .{
401 name_cty.fmtTypeName(zcu),371 name_cty.fmtTypeName(zcu),
...@@ -406,18 +376,18 @@ fn defineTuple(...@@ -406,18 +376,18 @@ fn defineTuple(
406 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {376 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| {
407 if (field_val_ip != .none) continue; // `comptime` field377 if (field_val_ip != .none) continue; // `comptime` field
408 const field_ty: Type = .fromInterned(field_ty_ip);378 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);
410 if (!field_ty.hasRuntimeBits(zcu)) continue;381 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);
412 try w.writeByte(' ');383 try w.writeByte(' ');
413 if (zig_offset == 0 and overalign) {384 if (zig_offset == 0 and overalign) {
414 // This is the first field; specify its alignment to align the tuple.385 // This is the first field; specify its alignment to align the tuple.
415 try writeFieldAlign(field_ty, tuple_align, w, zcu);386 try writeFieldAlign(field_ty, tuple_align, w, zcu);
416 } else if (zig_offset > c_offset) {387 } else if (zig_offset > c_offset) {
417 // This field needs to be underaligned or overaligned compared to what its388 // This field needs to be overaligned compared to what its offset would otherwise be.
418 // offset would otherwise be.
419 const need_align: Alignment = .minStrict(389 const need_align: Alignment = .minStrict(
420 tuple_align, // don't make the tuple more aligned than it should be390 tuple_align, // don't make the struct more aligned than it should be
421 .fromLog2Units(@ctz(zig_offset)),391 .fromLog2Units(@ctz(zig_offset)),
422 );392 );
423 try writeFieldAlign(field_ty, need_align, w, zcu);393 try writeFieldAlign(field_ty, need_align, w, zcu);
...@@ -433,9 +403,7 @@ fn defineTuple(...@@ -433,9 +403,7 @@ fn defineTuple(
433 zig_offset += field_size;403 zig_offset += field_size;
434 c_offset += field_size;404 c_offset += field_size;
435 }405 }
436 try w.writeByte('}');406 try w.writeAll("};\n");
437 if (pack) try w.writeByte(')');
438 try w.writeAll(";\n");
439407
440 try writeStaticAssertLayout(ty, name_cty, w, zcu);408 try writeStaticAssertLayout(ty, name_cty, w, zcu);
441}409}
...@@ -553,7 +521,7 @@ fn defineUnionAuto(...@@ -553,7 +521,7 @@ fn defineUnionAuto(
553 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {521 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
554 const field_ty: Type = .fromInterned(field_ty_ip);522 const field_ty: Type = .fromInterned(field_ty_ip);
555 if (!field_ty.hasRuntimeBits(zcu)) continue;523 if (!field_ty.hasRuntimeBits(zcu)) continue;
556 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);524 const natural_align = field_ty.abiAlignment(zcu);
557 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;525 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
558 // The tag will immediately follow the payload. This layout may put the tag in what would526 // The tag will immediately follow the payload. This layout may put the tag in what would
559 // otherwise be padding on the payload union, because if the most-aligned union field is not527 // otherwise be padding on the payload union, because if the most-aligned union field is not
...@@ -571,7 +539,7 @@ fn defineUnionAuto(...@@ -571,7 +539,7 @@ fn defineUnionAuto(
571 false => for (union_type.field_types.get(ip)) |field_ty_ip| {539 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
572 const field_ty: Type = .fromInterned(field_ty_ip);540 const field_ty: Type = .fromInterned(field_ty_ip);
573 if (!field_ty.hasRuntimeBits(zcu)) continue;541 if (!field_ty.hasRuntimeBits(zcu)) continue;
574 const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu);542 const natural_align = field_ty.abiAlignment(zcu);
575 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;543 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
576 } else overalign: {544 } else overalign: {
577 if (union_type.has_runtime_tag) {545 if (union_type.has_runtime_tag) {
...@@ -642,7 +610,7 @@ fn defineUnionExtern(...@@ -642,7 +610,7 @@ fn defineUnionExtern(
642 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {610 const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| {
643 const field_ty: Type = .fromInterned(field_ty_ip);611 const field_ty: Type = .fromInterned(field_ty_ip);
644 if (!field_ty.hasRuntimeBits(zcu)) continue;612 if (!field_ty.hasRuntimeBits(zcu)) continue;
645 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);613 const natural_align = field_ty.abiAlignment(zcu);
646 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;614 if (natural_align.compareStrict(.gt, union_type.alignment)) break true;
647 } else false;615 } else false;
648616
...@@ -654,7 +622,7 @@ fn defineUnionExtern(...@@ -654,7 +622,7 @@ fn defineUnionExtern(
654 false => for (union_type.field_types.get(ip)) |field_ty_ip| {622 false => for (union_type.field_types.get(ip)) |field_ty_ip| {
655 const field_ty: Type = .fromInterned(field_ty_ip);623 const field_ty: Type = .fromInterned(field_ty_ip);
656 if (!field_ty.hasRuntimeBits(zcu)) continue;624 if (!field_ty.hasRuntimeBits(zcu)) continue;
657 const natural_align = field_ty.defaultStructFieldAlignment(.@"extern", zcu);625 const natural_align = field_ty.abiAlignment(zcu);
658 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;626 if (natural_align.compareStrict(.gte, union_type.alignment)) break false;
659 } else overalign: {627 } else overalign: {
660 if (union_type.has_runtime_tag) {628 if (union_type.has_runtime_tag) {
...@@ -704,7 +672,7 @@ fn writeFieldAlign(...@@ -704,7 +672,7 @@ fn writeFieldAlign(
704 w: *Writer,672 w: *Writer,
705 zcu: *const Zcu,673 zcu: *const Zcu,
706) Writer.Error!void {674) Writer.Error!void {
707 if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) {675 if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) {
708 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});676 try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?});
709 } else {677 } else {
710 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});678 try w.print("zig_align({d}) ", .{alignment.toByteUnits().?});