Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a7d56a0

Browse files
authoredMar 13, 2025
Unrolled build for rust-lang#137816
Rollup merge of rust-lang#137816 - folkertdev:naked-asm-xcoff, r=Noratrieb attempt to support `BinaryFormat::Xcoff` in `naked_asm!` Fixes rust-lang#137219 So, the inline assembly support for xcoff is extremely limited. The LLVM [XCOFFAsmParser](https://github.com/llvm/llvm-project/blob/1b25c0c4da968fe78921ce77736e5baef4db75e3/llvm/lib/MC/MCParser/XCOFFAsmParser.cpp) does not support many of the attributes that LLVM itself emits, and that should exist based on [the assembler docs](https://www.ibm.com/docs/en/ssw_aix_71/assembler/assembler_pdf.pdf). It also does accept some that should not exist based on those docs. So, I've tried to do the best I can given those limitations. At least it's better than emitting the directives for elf and having that fail somewhere deep in LLVM. Given that inline assembly for this target is incomplete (under `asm_experimental_arch`), I think that's OK (and again I don't see how we can do better given the limitations in LLVM). r? ```@Noratrieb``` (given that you reviewed rust-lang#136637) It seems reasonable to ping the [`powerpc64-ibm-aix` target maintainers](https://doc.rust-lang.org/rustc/platform-support/aix.html), hopefully they have thoughts too: ```@daltenty``` ```@gilamn5tr```
2 parents a2aba05 + f35bda3 commit a7d56a0

File tree

5 files changed

+76
-9
lines changed

5 files changed

+76
-9
lines changed
 

‎compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

+41-9
Original file line numberDiff line numberDiff line change
@@ -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,16 @@ 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: there is currently no way of defining a weak symbol in inline assembly
166+
// for AIX. See https://github.com/llvm/llvm-project/issues/130269
167+
emit_fatal(
168+
"cannot create weak symbols from inline assembly for this target",
169+
)
170+
}
166171
BinaryFormat::MachO => {
167172
writeln!(w, ".globl {asm_name}")?;
168173
writeln!(w, ".weak_definition {asm_name}")?;
@@ -189,7 +194,7 @@ fn prefix_and_suffix<'tcx>(
189194
let mut begin = String::new();
190195
let mut end = String::new();
191196
match asm_binary_format {
192-
BinaryFormat::Elf | BinaryFormat::Xcoff => {
197+
BinaryFormat::Elf => {
193198
let section = link_section.unwrap_or(format!(".text.{asm_name}"));
194199

195200
let progbits = match is_arm {
@@ -203,7 +208,7 @@ fn prefix_and_suffix<'tcx>(
203208
};
204209

205210
writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap();
206-
writeln!(begin, ".balign {align}").unwrap();
211+
writeln!(begin, ".balign {align_bytes}").unwrap();
207212
write_linkage(&mut begin).unwrap();
208213
if let Visibility::Hidden = item_data.visibility {
209214
writeln!(begin, ".hidden {asm_name}").unwrap();
@@ -224,7 +229,7 @@ fn prefix_and_suffix<'tcx>(
224229
BinaryFormat::MachO => {
225230
let section = link_section.unwrap_or("__TEXT,__text".to_string());
226231
writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap();
227-
writeln!(begin, ".balign {align}").unwrap();
232+
writeln!(begin, ".balign {align_bytes}").unwrap();
228233
write_linkage(&mut begin).unwrap();
229234
if let Visibility::Hidden = item_data.visibility {
230235
writeln!(begin, ".private_extern {asm_name}").unwrap();
@@ -240,7 +245,7 @@ fn prefix_and_suffix<'tcx>(
240245
BinaryFormat::Coff => {
241246
let section = link_section.unwrap_or(format!(".text.{asm_name}"));
242247
writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
243-
writeln!(begin, ".balign {align}").unwrap();
248+
writeln!(begin, ".balign {align_bytes}").unwrap();
244249
write_linkage(&mut begin).unwrap();
245250
writeln!(begin, ".def {asm_name}").unwrap();
246251
writeln!(begin, ".scl 2").unwrap();
@@ -279,6 +284,33 @@ fn prefix_and_suffix<'tcx>(
279284
// .size is ignored for function symbols, so we can skip it
280285
writeln!(end, "end_function").unwrap();
281286
}
287+
BinaryFormat::Xcoff => {
288+
// the LLVM XCOFFAsmParser is extremely incomplete and does not implement many of the
289+
// documented directives.
290+
//
291+
// - https://github.com/llvm/llvm-project/blob/1b25c0c4da968fe78921ce77736e5baef4db75e3/llvm/lib/MC/MCParser/XCOFFAsmParser.cpp
292+
// - https://www.ibm.com/docs/en/ssw_aix_71/assembler/assembler_pdf.pdf
293+
//
294+
// Consequently, we try our best here but cannot do as good a job as for other binary
295+
// formats.
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)

‎tests/assembly/naked-functions/aix.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//@ revisions: elfv1-be aix
2+
//@ add-core-stubs
3+
//@ assembly-output: emit-asm
4+
//
5+
//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu
6+
//@[elfv1-be] needs-llvm-components: powerpc
7+
//
8+
//@[aix] compile-flags: --target powerpc64-ibm-aix
9+
//@[aix] needs-llvm-components: powerpc
10+
11+
#![crate_type = "lib"]
12+
#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)]
13+
#![no_core]
14+
15+
// tests that naked functions work for the `powerpc64-ibm-aix` target.
16+
//
17+
// This target is special because it uses the XCOFF binary format
18+
// It is tested alongside an elf powerpc target to pin down commonalities and differences.
19+
//
20+
// https://doc.rust-lang.org/rustc/platform-support/aix.html
21+
// https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format
22+
23+
extern crate minicore;
24+
use minicore::*;
25+
26+
// elfv1-be: .p2align 2
27+
// aix: .align 2
28+
// CHECK: .globl blr
29+
// CHECK-LABEL: blr:
30+
// CHECK: blr
31+
#[no_mangle]
32+
#[naked]
33+
unsafe extern "C" fn blr() {
34+
naked_asm!("blr")
35+
}
File renamed without changes.

0 commit comments

Comments
 (0)
Failed to load comments.