Skip to content

Commit 2aa8ad6

Browse files
authored
Rollup merge of #103897 - Amanieu:llvm-58384, r=davidtwco
asm: Work around LLVM bug on AArch64 Upstream issue: llvm/llvm-project#58384 LLVM gets confused if we assign a 32-bit value to a 64-bit register, so pass the 32-bit register name to LLVM in that case.
2 parents 1cb8684 + 03e4c76 commit 2aa8ad6

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

+54-3
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,44 @@ fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> {
505505
}
506506
}
507507

508+
/// If the register is an AArch64 integer register then return its index.
509+
fn a64_reg_index(reg: InlineAsmReg) -> Option<u32> {
510+
match reg {
511+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x0) => Some(0),
512+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x1) => Some(1),
513+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x2) => Some(2),
514+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x3) => Some(3),
515+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x4) => Some(4),
516+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x5) => Some(5),
517+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x6) => Some(6),
518+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x7) => Some(7),
519+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x8) => Some(8),
520+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x9) => Some(9),
521+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x10) => Some(10),
522+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x11) => Some(11),
523+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x12) => Some(12),
524+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x13) => Some(13),
525+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x14) => Some(14),
526+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x15) => Some(15),
527+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x16) => Some(16),
528+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x17) => Some(17),
529+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x18) => Some(18),
530+
// x19 is reserved
531+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x20) => Some(20),
532+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x21) => Some(21),
533+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x22) => Some(22),
534+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x23) => Some(23),
535+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x24) => Some(24),
536+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x25) => Some(25),
537+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x26) => Some(26),
538+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x27) => Some(27),
539+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x28) => Some(28),
540+
// x29 is reserved
541+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) => Some(30),
542+
_ => None,
543+
}
544+
}
545+
508546
/// If the register is an AArch64 vector register then return its index.
509547
fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> {
510548
match reg {
@@ -535,6 +573,22 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
535573
'x'
536574
};
537575
format!("{{{}mm{}}}", class, idx)
576+
} else if let Some(idx) = a64_reg_index(reg) {
577+
let class = if let Some(layout) = layout {
578+
match layout.size.bytes() {
579+
8 => 'x',
580+
_ => 'w',
581+
}
582+
} else {
583+
// We use i32 as the type for discarded outputs
584+
'w'
585+
};
586+
if class == 'x' && reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
587+
// LLVM doesn't recognize x30. use lr instead.
588+
"{lr}".to_string()
589+
} else {
590+
format!("{{{}{}}}", class, idx)
591+
}
538592
} else if let Some(idx) = a64_vreg_index(reg) {
539593
let class = if let Some(layout) = layout {
540594
match layout.size.bytes() {
@@ -550,9 +604,6 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
550604
'q'
551605
};
552606
format!("{{{}{}}}", class, idx)
553-
} else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
554-
// LLVM doesn't recognize x30
555-
"{lr}".to_string()
556607
} else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) {
557608
// LLVM doesn't recognize r14
558609
"{lr}".to_string()

src/test/ui/asm/aarch64/llvm-58384.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// only-aarch64
2+
// run-pass
3+
// needs-asm-support
4+
5+
// Test that we properly work around this LLVM issue:
6+
// https://github.com/llvm/llvm-project/issues/58384
7+
8+
use std::arch::asm;
9+
10+
fn main() {
11+
let a: i32;
12+
unsafe {
13+
asm!("", inout("x0") 435 => a);
14+
}
15+
assert_eq!(a, 435);
16+
}

0 commit comments

Comments
 (0)