@@ -125,7 +125,8 @@ fn prefix_and_suffix<'tcx>(
125125 // the alignment from a `#[repr(align(<n>))]` is used if it specifies a higher alignment.
126126 // if no alignment is specified, an alignment of 4 bytes is used.
127127 let min_function_alignment = tcx. sess . opts . unstable_opts . min_function_alignment ;
128- let align = Ord :: max ( min_function_alignment, attrs. alignment ) . map ( |a| a. bytes ( ) ) . unwrap_or ( 4 ) ;
128+ let align_bytes =
129+ Ord :: max ( min_function_alignment, attrs. alignment ) . map ( |a| a. bytes ( ) ) . unwrap_or ( 4 ) ;
129130
130131 // In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`.
131132 let ( arch_prefix, arch_suffix) = if is_arm {
@@ -157,12 +158,17 @@ fn prefix_and_suffix<'tcx>(
157158 }
158159 Linkage :: LinkOnceAny | Linkage :: LinkOnceODR | Linkage :: WeakAny | Linkage :: WeakODR => {
159160 match asm_binary_format {
160- BinaryFormat :: Elf
161- | BinaryFormat :: Coff
162- | BinaryFormat :: Wasm
163- | BinaryFormat :: Xcoff => {
161+ BinaryFormat :: Elf | BinaryFormat :: Coff | BinaryFormat :: Wasm => {
164162 writeln ! ( w, ".weak {asm_name}" ) ?;
165163 }
164+ BinaryFormat :: Xcoff => {
165+ // FIXME: .weak_definition is accepted by the assembly parser, but is not
166+ // documented https://www.ibm.com/docs/en/ssw_aix_71/assembler/assembler_pdf.pdf
167+ // For all I know, it might just be ignored.
168+ //
169+ // On the other hand `.weak` is documented, but rejected as an "unknown directive".
170+ writeln ! ( w, ".weak_definition {asm_name}" ) ?;
171+ }
166172 BinaryFormat :: MachO => {
167173 writeln ! ( w, ".globl {asm_name}" ) ?;
168174 writeln ! ( w, ".weak_definition {asm_name}" ) ?;
@@ -189,7 +195,7 @@ fn prefix_and_suffix<'tcx>(
189195 let mut begin = String :: new ( ) ;
190196 let mut end = String :: new ( ) ;
191197 match asm_binary_format {
192- BinaryFormat :: Elf | BinaryFormat :: Xcoff => {
198+ BinaryFormat :: Elf => {
193199 let section = link_section. unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
194200
195201 let progbits = match is_arm {
@@ -203,7 +209,7 @@ fn prefix_and_suffix<'tcx>(
203209 } ;
204210
205211 writeln ! ( begin, ".pushsection {section},\" ax\" , {progbits}" ) . unwrap ( ) ;
206- writeln ! ( begin, ".balign {align }" ) . unwrap ( ) ;
212+ writeln ! ( begin, ".balign {align_bytes }" ) . unwrap ( ) ;
207213 write_linkage ( & mut begin) . unwrap ( ) ;
208214 if let Visibility :: Hidden = item_data. visibility {
209215 writeln ! ( begin, ".hidden {asm_name}" ) . unwrap ( ) ;
@@ -224,7 +230,7 @@ fn prefix_and_suffix<'tcx>(
224230 BinaryFormat :: MachO => {
225231 let section = link_section. unwrap_or ( "__TEXT,__text" . to_string ( ) ) ;
226232 writeln ! ( begin, ".pushsection {},regular,pure_instructions" , section) . unwrap ( ) ;
227- writeln ! ( begin, ".balign {align }" ) . unwrap ( ) ;
233+ writeln ! ( begin, ".balign {align_bytes }" ) . unwrap ( ) ;
228234 write_linkage ( & mut begin) . unwrap ( ) ;
229235 if let Visibility :: Hidden = item_data. visibility {
230236 writeln ! ( begin, ".private_extern {asm_name}" ) . unwrap ( ) ;
@@ -240,7 +246,7 @@ fn prefix_and_suffix<'tcx>(
240246 BinaryFormat :: Coff => {
241247 let section = link_section. unwrap_or ( format ! ( ".text.{asm_name}" ) ) ;
242248 writeln ! ( begin, ".pushsection {},\" xr\" " , section) . unwrap ( ) ;
243- writeln ! ( begin, ".balign {align }" ) . unwrap ( ) ;
249+ writeln ! ( begin, ".balign {align_bytes }" ) . unwrap ( ) ;
244250 write_linkage ( & mut begin) . unwrap ( ) ;
245251 writeln ! ( begin, ".def {asm_name}" ) . unwrap ( ) ;
246252 writeln ! ( begin, ".scl 2" ) . unwrap ( ) ;
@@ -279,6 +285,32 @@ fn prefix_and_suffix<'tcx>(
279285 // .size is ignored for function symbols, so we can skip it
280286 writeln ! ( end, "end_function" ) . unwrap ( ) ;
281287 }
288+ BinaryFormat :: Xcoff => {
289+ // the LLVM XCOFFAsmParser extremely is incomplete.
290+ //
291+ // https://github.com/llvm/llvm-project/blob/1b25c0c4da968fe78921ce77736e5baef4db75e3/llvm/lib/MC/MCParser/XCOFFAsmParser.cpp
292+ //
293+ // and does not implement many of the documented directives from https://www.ibm.com/docs/en/ssw_aix_71/assembler/assembler_pdf.pdf
294+ //
295+ // Consequently, we try our best here but cannot do as good a job as for other targets.
296+
297+ // FIXME: start a section. `.csect` is not currently implemented in LLVM
298+
299+ // fun fact: according to the assembler documentation, .align takes an exponent,
300+ // but LLVM only accepts powers of 2 (but does emit the exponent)
301+ // so when we hand `.align 32` to LLVM, the assembly output will contain `.align 5`
302+ writeln ! ( begin, ".align {}" , align_bytes) . unwrap ( ) ;
303+
304+ write_linkage ( & mut begin) . unwrap ( ) ;
305+ if let Visibility :: Hidden = item_data. visibility {
306+ // FIXME apparently `.globl {asm_name}, hidden` is valid
307+ // but due to limitations with `.weak` (see above) we can't really use that in general yet
308+ }
309+ writeln ! ( begin, "{asm_name}:" ) . unwrap ( ) ;
310+
311+ writeln ! ( end) . unwrap ( ) ;
312+ // FIXME: end the section?
313+ }
282314 }
283315
284316 ( begin, end)
0 commit comments