Summary
The .comm directive's third operand is emitted as a hardcoded 3 for every target, but
that operand means different things on Mach-O and ELF:
- Mach-O (
as/clang): alignment as a power of two — 3 means 8-byte alignment.
- ELF (GNU
as): alignment in bytes — 3 means 3-byte alignment, which is not a
power of two at all.
Where
src/codegen_support/data_section.rs:165:
for (label, size) in &self.comm_entries {
out.push_str(&format!(".comm {}, {}, 3\n", label, size));
}
emit() takes no target parameter, so there is no way for the value to follow the object
format. Every common symbol in the program goes through this one site — the static-local
slots, the define() seen-flags, IR globals, the function-variant active symbols, the
concat scratch, and the stack-limit slot.
Why it surfaced
Adding _stack_limit as a common symbol for the stack-exhaustion guard made this reachable
on Linux images that had not previously been exercised with a fresh .comm symbol.
Expected
Emit the alignment the way the target's assembler reads it: the log2 exponent for Mach-O,
the byte count for ELF. Both should express the same intended 8-byte alignment.
Note
This is an assembler-syntax portability bug, not a codegen logic bug — the sizes and labels
are correct. It is worth an audit of the other directives emitted from the same section for
the same class of Mach-O/ELF operand divergence.
Summary
The
.commdirective's third operand is emitted as a hardcoded3for every target, butthat operand means different things on Mach-O and ELF:
as/clang): alignment as a power of two —3means 8-byte alignment.as): alignment in bytes —3means 3-byte alignment, which is not apower of two at all.
Where
src/codegen_support/data_section.rs:165:emit()takes no target parameter, so there is no way for the value to follow the objectformat. Every common symbol in the program goes through this one site — the static-local
slots, the
define()seen-flags, IR globals, the function-variant active symbols, theconcat scratch, and the stack-limit slot.
Why it surfaced
Adding
_stack_limitas a common symbol for the stack-exhaustion guard made this reachableon Linux images that had not previously been exercised with a fresh
.commsymbol.Expected
Emit the alignment the way the target's assembler reads it: the log2 exponent for Mach-O,
the byte count for ELF. Both should express the same intended 8-byte alignment.
Note
This is an assembler-syntax portability bug, not a codegen logic bug — the sizes and labels
are correct. It is worth an audit of the other directives emitted from the same section for
the same class of Mach-O/ELF operand divergence.