From 7a27a99b784789a7654043f6e55d9d20ea63b2d3 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Wed, 22 Jul 2026 21:42:11 +0000
Subject: [PATCH 13/30] trans: emit explicit aligned attribute for repr(align)
 structs

codegen_c only emitted __attribute__((aligned(N))) when the computed
alignment differed from the largest field's Rust-side alignment, so a
repr(align(8)) struct whose fields already include an 8-aligned type got
no attribute. On Darwin ppc32 the C compiler's natural alignment for
such a struct can be lower (8-byte fields are capped to 4 unless the
type carries a user alignment), so the attribute is required.

Seen with libc 0.2.174 tcp_connection_info (repr(align(8)), first field
u8, u64 tail): mrustc computed 176/8 but the emitted C struct laid out
as 172/4, failing the sizeof/alignof asserts.

target.cpp's darwin_ppc32_type_has_c_user_align already models
repr(align) structs as carrying the attribute; this makes codegen match
that model. No-op on natural-alignment targets, where the attribute
merely restates the alignment the compiler derives anyway.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wCVW89GjmNyYviEcANPHM
---
 src/trans/codegen_c.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index a4673b7e..a66c1d1d 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -1776,6 +1776,16 @@ namespace {
             if(packing_max_align == 0 && max_align != repr->align /*&& repr->size > 0*/) {
                 has_manual_align = true;
             }
+            // repr(align(N)): always emit an explicit alignment attribute. The C compiler can't
+            // infer a user-specified alignment from the field list when it happens to equal the
+            // largest field alignment - and on Darwin ppc32 the C compiler's natural alignment
+            // for the emitted fields can be lower than `repr->align` (fields are capped to 4).
+            // Mirrored by `darwin_ppc32_type_has_c_user_align` in target.cpp.
+            if(packing_max_align == 0 && ty.data().is_Path() && ty.data().as_Path().binding.is_Struct())
+            {
+                if( ty.data().as_Path().binding.as_Struct()->m_forced_alignment > 0 )
+                    has_manual_align = true;
+            }
             // - Sort the fields by offset
             ::std::sort(fields.begin(), fields.end(), [&](auto a, auto b){
                 if( repr->fields[a].offset == repr->fields[b].offset )
-- 
2.43.0

