Skip to content

Commit 2577662

Browse files
committed
support XCOFF in naked_asm!
1 parent c620d76 commit 2577662

File tree

2 files changed

+93
-9
lines changed

2 files changed

+93
-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,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)

tests/assembly/naked-functions/aix.rs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
}
36+
37+
// CHECK-NOT: .globl weak_aligned_blr
38+
//
39+
// elfv1-be: .p2align 5
40+
// aix: .align 5
41+
//
42+
// elfv1-be: .weak weak_aligned_blr
43+
// aix: .weak_definition weak_aligned_blr
44+
//
45+
// CHECK-LABEL: weak_aligned_blr:
46+
#[no_mangle]
47+
#[naked]
48+
#[linkage = "weak"]
49+
#[repr(align(32))]
50+
unsafe extern "C" fn weak_aligned_blr() {
51+
naked_asm!("blr")
52+
}

0 commit comments

Comments
 (0)