@@ -617,12 +617,24 @@ impl EmitAsm for Directive {
617617 }
618618 }
619619 Directive :: Comm { sym, size, align } => {
620+ // macOS uses log2(alignment) for .comm, Linux uses byte alignment
621+ let align_value = match target. os {
622+ Os :: MacOS => {
623+ // Convert byte alignment to log2
624+ if * align == 0 {
625+ 0
626+ } else {
627+ align. trailing_zeros ( )
628+ }
629+ }
630+ Os :: Linux | Os :: FreeBSD => * align,
631+ } ;
620632 let _ = writeln ! (
621633 out,
622634 ".comm {},{},{}" ,
623635 sym. format_for_target( target) ,
624636 size,
625- align
637+ align_value
626638 ) ;
627639 }
628640
@@ -890,13 +902,58 @@ mod tests {
890902 fn test_directive_comm ( ) {
891903 let linux = Target :: new ( Arch :: X86_64 , Os :: Linux ) ;
892904 let macos = Target :: new ( Arch :: X86_64 , Os :: MacOS ) ;
905+ let freebsd = Target :: new ( Arch :: X86_64 , Os :: FreeBSD ) ;
893906
907+ // Linux uses byte alignment directly
894908 let mut out = String :: new ( ) ;
895909 Directive :: comm ( "my_var" , 8 , 8 ) . emit ( & linux, & mut out) ;
896910 assert_eq ! ( out, ".comm my_var,8,8\n " ) ;
897911
912+ // macOS uses log2(alignment): 8 bytes = 2^3, so log2(8) = 3
898913 let mut out = String :: new ( ) ;
899914 Directive :: comm ( "my_var" , 8 , 8 ) . emit ( & macos, & mut out) ;
900- assert_eq ! ( out, ".comm _my_var,8,8\n " ) ;
915+ assert_eq ! ( out, ".comm _my_var,8,3\n " ) ;
916+
917+ // FreeBSD uses byte alignment like Linux
918+ let mut out = String :: new ( ) ;
919+ Directive :: comm ( "my_var" , 8 , 8 ) . emit ( & freebsd, & mut out) ;
920+ assert_eq ! ( out, ".comm my_var,8,8\n " ) ;
921+
922+ // Test alignment=1: macOS log2(1)=0, Linux/FreeBSD=1
923+ let mut out = String :: new ( ) ;
924+ Directive :: comm ( "byte_var" , 1 , 1 ) . emit ( & linux, & mut out) ;
925+ assert_eq ! ( out, ".comm byte_var,1,1\n " ) ;
926+
927+ let mut out = String :: new ( ) ;
928+ Directive :: comm ( "byte_var" , 1 , 1 ) . emit ( & macos, & mut out) ;
929+ assert_eq ! ( out, ".comm _byte_var,1,0\n " ) ;
930+
931+ // Test alignment=2: macOS log2(2)=1, Linux=2
932+ let mut out = String :: new ( ) ;
933+ Directive :: comm ( "short_var" , 2 , 2 ) . emit ( & linux, & mut out) ;
934+ assert_eq ! ( out, ".comm short_var,2,2\n " ) ;
935+
936+ let mut out = String :: new ( ) ;
937+ Directive :: comm ( "short_var" , 2 , 2 ) . emit ( & macos, & mut out) ;
938+ assert_eq ! ( out, ".comm _short_var,2,1\n " ) ;
939+
940+ // Test alignment=4: macOS log2(4)=2, Linux=4
941+ let mut out = String :: new ( ) ;
942+ Directive :: comm ( "int_var" , 4 , 4 ) . emit ( & linux, & mut out) ;
943+ assert_eq ! ( out, ".comm int_var,4,4\n " ) ;
944+
945+ let mut out = String :: new ( ) ;
946+ Directive :: comm ( "int_var" , 4 , 4 ) . emit ( & macos, & mut out) ;
947+ assert_eq ! ( out, ".comm _int_var,4,2\n " ) ;
948+
949+ // Test alignment=16: macOS log2(16)=4, Linux=16
950+ // (used for large arrays per clang's LargeArrayMinWidth)
951+ let mut out = String :: new ( ) ;
952+ Directive :: comm ( "big_array" , 64 , 16 ) . emit ( & linux, & mut out) ;
953+ assert_eq ! ( out, ".comm big_array,64,16\n " ) ;
954+
955+ let mut out = String :: new ( ) ;
956+ Directive :: comm ( "big_array" , 64 , 16 ) . emit ( & macos, & mut out) ;
957+ assert_eq ! ( out, ".comm _big_array,64,4\n " ) ;
901958 }
902959}
0 commit comments