Skip to content

Commit

Permalink
Fix handling of x18 in AArch64 inline assembly on ohos/trusty or with…
Browse files Browse the repository at this point in the history
… -Zfixed-x18
  • Loading branch information
taiki-e committed Nov 25, 2024
1 parent 7db7489 commit a43aa35
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 51 deletions.
7 changes: 6 additions & 1 deletion compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let mut clobber_abis = FxIndexMap::default();
if let Some(asm_arch) = asm_arch {
for (abi_name, abi_span) in &asm.clobber_abis {
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) {
match asm::InlineAsmClobberAbi::parse(
asm_arch,
&self.tcx.sess.target,
&self.tcx.sess.unstable_target_features,
*abi_name,
) {
Ok(abi) => {
// If the abi was already in the list, emit an error
match clobber_abis.get(&abi) {
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_codegen_cranelift/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,9 +476,14 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);

// Allocate stack slots for saving clobbered registers
let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C)
.unwrap()
.clobbered_regs();
let abi_clobber = InlineAsmClobberAbi::parse(
self.arch,
&self.tcx.sess.target,
&self.tcx.sess.unstable_target_features,
sym::C,
)
.unwrap()
.clobbered_regs();
for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) {
let mut need_save = true;
// If the register overlaps with a register clobbered by function call, then
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,7 @@ symbols! {
repr_simd,
repr_transparent,
require,
reserve_x18: "reserve-x18",
residual,
result,
result_ffi_guarantees,
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_target/src/asm/aarch64.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

use rustc_data_structures::fx::FxIndexSet;
use rustc_span::Symbol;
use rustc_span::{Symbol, sym};

use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
Expand Down Expand Up @@ -71,18 +71,26 @@ impl AArch64InlineAsmRegClass {
}
}

pub(crate) fn target_reserves_x18(target: &Target) -> bool {
target.os == "android" || target.os == "fuchsia" || target.is_like_osx || target.is_like_windows
pub(crate) fn target_reserves_x18(target: &Target, target_features: &FxIndexSet<Symbol>) -> bool {
// See isX18ReservedByDefault in LLVM for targets reserve x18 by default:
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/TargetParser/AArch64TargetParser.cpp#L102-L105
// Note that +reserve-x18 is currently not set for the above targets.
target.os == "android"
|| target.os == "fuchsia"
|| target.env == "ohos"
|| target.is_like_osx
|| target.is_like_windows
|| target_features.contains(&sym::reserve_x18)
}

fn reserved_x18(
_arch: InlineAsmArch,
_reloc_model: RelocModel,
_target_features: &FxIndexSet<Symbol>,
target_features: &FxIndexSet<Symbol>,
target: &Target,
_is_clobber: bool,
) -> Result<(), &'static str> {
if target_reserves_x18(target) {
if target_reserves_x18(target, target_features) {
Err("x18 is a reserved register on this target")
} else {
Ok(())
Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_target/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@ impl InlineAsmClobberAbi {
pub fn parse(
arch: InlineAsmArch,
target: &Target,
target_features: &FxIndexSet<Symbol>,
name: Symbol,
) -> Result<Self, &'static [&'static str]> {
let name = name.as_str();
Expand All @@ -963,11 +964,13 @@ impl InlineAsmClobberAbi {
_ => Err(&["C", "system", "efiapi", "aapcs"]),
},
InlineAsmArch::AArch64 => match name {
"C" | "system" | "efiapi" => Ok(if aarch64::target_reserves_x18(target) {
InlineAsmClobberAbi::AArch64NoX18
} else {
InlineAsmClobberAbi::AArch64
}),
"C" | "system" | "efiapi" => {
Ok(if aarch64::target_reserves_x18(target, target_features) {
InlineAsmClobberAbi::AArch64NoX18
} else {
InlineAsmClobberAbi::AArch64
})
}
_ => Err(&["C", "system", "efiapi"]),
},
InlineAsmArch::Arm64EC => match name {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
arch: "aarch64".into(),
options: TargetOptions {
features: "+reserve-x18".into(),
mcount: "\u{1}_mcount".into(),
stack_probes: StackProbeType::Inline,
supported_sanitizers: SanitizerSet::ADDRESS
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("rcpc2", Stable, &["rcpc"]),
// FEAT_LRCPC3
("rcpc3", Unstable(sym::aarch64_unstable_target_feature), &["rcpc2"]),
// This is needed for inline assembly, but shouldn't be stabilized as-is
// since it should be enabled globally using -Zfixed-x18, not
// #[target_feature].
// Note that cfg(target_feature = "reserve-x18") is currently not set for
// targets that reserve x18 by default.
("reserve-x18", Unstable(sym::aarch64_unstable_target_feature), &[]),
// FEAT_RDM
("rdm", Stable, &["neon"]),
// FEAT_SB
Expand Down
52 changes: 52 additions & 0 deletions tests/codegen/asm/aarch64-clobbers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//@ assembly-output: emit-asm
//@ revisions: aarch64 aarch64_fixed_x18 aarch64_no_x18 aarch64_reserve_x18 arm64ec
//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
//@[aarch64] needs-llvm-components: aarch64
//@[aarch64_fixed_x18] compile-flags: --target aarch64-unknown-linux-gnu -Zfixed-x18
//@[aarch64_fixed_x18] needs-llvm-components: aarch64
//@[aarch64_no_x18] compile-flags: --target aarch64-pc-windows-msvc
//@[aarch64_no_x18] needs-llvm-components: aarch64
// aarch64-unknown-trusty uses aarch64-unknown-unknown-musl which doesn't
// reserve x18 by default as llvm_target, and pass +reserve-x18 in target-spec.
//@[aarch64_reserve_x18] compile-flags: --target aarch64-unknown-trusty
//@[aarch64_reserve_x18] needs-llvm-components: aarch64
//@[arm64ec] compile-flags: --target arm64ec-pc-windows-msvc
//@[arm64ec] needs-llvm-components: aarch64
// ignore-tidy-filelength

#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items)]
#![no_core]

#[lang = "sized"]
trait Sized {}

#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}

// CHECK-LABEL: @cc_clobber
// CHECK: call void asm sideeffect "", "~{cc}"()
#[no_mangle]
pub unsafe fn cc_clobber() {
asm!("", options(nostack, nomem));
}

// CHECK-LABEL: @no_clobber
// CHECK: call void asm sideeffect "", ""()
#[no_mangle]
pub unsafe fn no_clobber() {
asm!("", options(nostack, nomem, preserves_flags));
}

// CHECK-LABEL: @clobber_abi
// aarch64: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w18},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"()
// aarch64_fixed_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"()
// aarch64_no_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"()
// aarch64_reserve_x18: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w13},={w14},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15},={q16},={q17},={q18},={q19},={q20},={q21},={q22},={q23},={q24},={q25},={q26},={q27},={q28},={q29},={q30},={q31},~{p0},~{p1},~{p2},~{p3},~{p4},~{p5},~{p6},~{p7},~{p8},~{p9},~{p10},~{p11},~{p12},~{p13},~{p14},~{p15},~{ffr}"()
// arm64ec: asm sideeffect "", "={w0},={w1},={w2},={w3},={w4},={w5},={w6},={w7},={w8},={w9},={w10},={w11},={w12},={w15},={w16},={w17},={w30},={q0},={q1},={q2},={q3},={q4},={q5},={q6},={q7},={q8},={q9},={q10},={q11},={q12},={q13},={q14},={q15}"()
#[no_mangle]
pub unsafe fn clobber_abi() {
asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
}
36 changes: 0 additions & 36 deletions tests/codegen/asm/arm64ec-clobbers.rs

This file was deleted.

0 comments on commit a43aa35

Please sign in to comment.