Skip to content

Commit

Permalink
On ARM, use relocation_model to detect whether r9 should be reserved
Browse files Browse the repository at this point in the history
The previous approach of checking for the reserve-r9 target feature
didn't actually work because LLVM only sets this feature very late when
initializing the per-function subtarget.
  • Loading branch information
Amanieu committed Feb 21, 2022
1 parent 2e8a766 commit 1ceb104
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 47 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/asm.rs
Expand Up @@ -66,6 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
for (abi_name, abi_span) in &asm.clobber_abis {
match asm::InlineAsmClobberAbi::parse(
asm_arch,
self.sess.relocation_model(),
&self.sess.target_features,
&self.sess.target,
*abi_name,
Expand Down Expand Up @@ -134,6 +135,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
asm::InlineAsmReg::parse(
asm_arch,
sess.relocation_model(),
&sess.target_features,
&sess.target,
is_clobber,
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_codegen_cranelift/src/inline_asm.rs
Expand Up @@ -182,7 +182,12 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
fn allocate_registers(&mut self) {
let sess = self.tcx.sess;
let map = allocatable_registers(self.arch, &sess.target_features, &sess.target);
let map = allocatable_registers(
self.arch,
sess.relocation_model(),
&sess.target_features,
&sess.target,
);
let mut allocated = FxHashMap::<_, (bool, bool)>::default();
let mut regs = vec![None; self.operands.len()];

Expand Down Expand Up @@ -315,6 +320,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate stack slots for saving clobbered registers
let abi_clobber = InlineAsmClobberAbi::parse(
self.arch,
self.tcx.sess.relocation_model(),
&self.tcx.sess.target_features,
&self.tcx.sess.target,
sym::C,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_ssa/src/target_features.rs
Expand Up @@ -36,7 +36,6 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
// #[target_feature].
("thumb-mode", Some(sym::arm_target_feature)),
("thumb2", Some(sym::arm_target_feature)),
("reserve-r9", Some(sym::arm_target_feature)),
];

const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/symbol.rs
Expand Up @@ -1122,7 +1122,6 @@ symbols! {
repr_packed,
repr_simd,
repr_transparent,
reserved_r9: "reserved-r9",
residual,
result,
rhs,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/asm/aarch64.rs
@@ -1,5 +1,5 @@
use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target;
use crate::spec::{Target, RelocModel};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
Expand Down Expand Up @@ -75,6 +75,7 @@ impl AArch64InlineAsmRegClass {

pub fn reserved_x18(
_arch: InlineAsmArch,
_reloc_model: RelocModel,
_target_features: &FxHashSet<Symbol>,
target: &Target,
_is_clobber: bool,
Expand Down
21 changes: 12 additions & 9 deletions compiler/rustc_target/src/asm/arm.rs
@@ -1,5 +1,5 @@
use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target;
use crate::spec::{RelocModel, Target};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
Expand Down Expand Up @@ -67,11 +67,12 @@ fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) ->

fn frame_pointer_r11(
arch: InlineAsmArch,
reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
target: &Target,
is_clobber: bool,
) -> Result<(), &'static str> {
not_thumb1(arch, target_features, target, is_clobber)?;
not_thumb1(arch, reloc_model, target_features, target, is_clobber)?;

if !frame_pointer_is_r7(target_features, target) {
Err("the frame pointer (r11) cannot be used as an operand for inline asm")
Expand All @@ -82,6 +83,7 @@ fn frame_pointer_r11(

fn frame_pointer_r7(
_arch: InlineAsmArch,
_reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
target: &Target,
_is_clobber: bool,
Expand All @@ -95,6 +97,7 @@ fn frame_pointer_r7(

fn not_thumb1(
_arch: InlineAsmArch,
_reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
_target: &Target,
is_clobber: bool,
Expand All @@ -111,18 +114,18 @@ fn not_thumb1(

fn reserved_r9(
arch: InlineAsmArch,
reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
target: &Target,
is_clobber: bool,
) -> Result<(), &'static str> {
not_thumb1(arch, target_features, target, is_clobber)?;
not_thumb1(arch, reloc_model, target_features, target, is_clobber)?;

// We detect this using the reserved-r9 feature instead of using the target
// because the relocation model can be changed with compiler options.
if target_features.contains(&sym::reserved_r9) {
Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
} else {
Ok(())
match reloc_model {
RelocModel::Rwpi | RelocModel::RopiRwpi => {
Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
}
_ => Ok(()),
}
}

Expand Down
69 changes: 37 additions & 32 deletions compiler/rustc_target/src/asm/mod.rs
@@ -1,5 +1,5 @@
use crate::abi::Size;
use crate::spec::Target;
use crate::{abi::Size, spec::RelocModel};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
Expand Down Expand Up @@ -81,6 +81,7 @@ macro_rules! def_regs {

pub fn parse(
_arch: super::InlineAsmArch,
_reloc_model: crate::spec::RelocModel,
_target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
_target: &crate::spec::Target,
_is_clobber: bool,
Expand All @@ -89,7 +90,7 @@ macro_rules! def_regs {
match name {
$(
$($alias)|* | $reg_name => {
$($filter(_arch, _target_features, _target, _is_clobber)?;)?
$($filter(_arch, _reloc_model, _target_features, _target, _is_clobber)?;)?
Ok(Self::$reg)
}
)*
Expand All @@ -103,6 +104,7 @@ macro_rules! def_regs {

pub(super) fn fill_reg_map(
_arch: super::InlineAsmArch,
_reloc_model: crate::spec::RelocModel,
_target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
_target: &crate::spec::Target,
_map: &mut rustc_data_structures::fx::FxHashMap<
Expand All @@ -113,7 +115,7 @@ macro_rules! def_regs {
#[allow(unused_imports)]
use super::{InlineAsmReg, InlineAsmRegClass};
$(
if $($filter(_arch, _target_features, _target, false).is_ok() &&)? true {
if $($filter(_arch, _reloc_model, _target_features, _target, false).is_ok() &&)? true {
if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
set.insert(InlineAsmReg::$arch($arch_reg::$reg));
}
Expand Down Expand Up @@ -297,6 +299,7 @@ impl InlineAsmReg {

pub fn parse(
arch: InlineAsmArch,
reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
target: &Target,
is_clobber: bool,
Expand All @@ -307,75 +310,75 @@ impl InlineAsmReg {
let name = name.as_str();
Ok(match arch {
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
Self::X86(X86InlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
Self::X86(X86InlineAsmReg::parse(arch, reloc_model,target_features, target, is_clobber, name)?)
}
InlineAsmArch::Arm => {
Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
Self::Arm(ArmInlineAsmReg::parse(arch, reloc_model,target_features, target, is_clobber, name)?)
}
InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => Self::RiscV(
RiscVInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
RiscVInlineAsmReg::parse(arch, reloc_model,target_features, target, is_clobber, name)?,
),
InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => Self::PowerPC(
PowerPCInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
PowerPCInlineAsmReg::parse(arch, reloc_model,target_features, target, is_clobber, name)?,
),
InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::Mips | InlineAsmArch::Mips64 => Self::Mips(MipsInlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => Self::Wasm(WasmInlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
)?),
InlineAsmArch::Bpf => {
Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
Self::Bpf(BpfInlineAsmReg::parse(arch, reloc_model,target_features, target, is_clobber, name)?)
}
InlineAsmArch::Avr => {
Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
Self::Avr(AvrInlineAsmReg::parse(arch, reloc_model,target_features, target, is_clobber, name)?)
}
InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(
arch,
target_features,
reloc_model,target_features,
target,
is_clobber,
name,
Expand Down Expand Up @@ -749,78 +752,79 @@ impl fmt::Display for InlineAsmType {
// falling back to an external assembler.
pub fn allocatable_registers(
arch: InlineAsmArch,
reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
target: &crate::spec::Target,
) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
match arch {
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
let mut map = x86::regclass_map();
x86::fill_reg_map(arch, target_features, target, &mut map);
x86::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Arm => {
let mut map = arm::regclass_map();
arm::fill_reg_map(arch, target_features, target, &mut map);
arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::AArch64 => {
let mut map = aarch64::regclass_map();
aarch64::fill_reg_map(arch, target_features, target, &mut map);
aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
let mut map = riscv::regclass_map();
riscv::fill_reg_map(arch, target_features, target, &mut map);
riscv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Nvptx64 => {
let mut map = nvptx::regclass_map();
nvptx::fill_reg_map(arch, target_features, target, &mut map);
nvptx::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
let mut map = powerpc::regclass_map();
powerpc::fill_reg_map(arch, target_features, target, &mut map);
powerpc::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Hexagon => {
let mut map = hexagon::regclass_map();
hexagon::fill_reg_map(arch, target_features, target, &mut map);
hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
let mut map = mips::regclass_map();
mips::fill_reg_map(arch, target_features, target, &mut map);
mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::S390x => {
let mut map = s390x::regclass_map();
s390x::fill_reg_map(arch, target_features, target, &mut map);
s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::SpirV => {
let mut map = spirv::regclass_map();
spirv::fill_reg_map(arch, target_features, target, &mut map);
spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
let mut map = wasm::regclass_map();
wasm::fill_reg_map(arch, target_features, target, &mut map);
wasm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Bpf => {
let mut map = bpf::regclass_map();
bpf::fill_reg_map(arch, target_features, target, &mut map);
bpf::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Avr => {
let mut map = avr::regclass_map();
avr::fill_reg_map(arch, target_features, target, &mut map);
avr::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
InlineAsmArch::Msp430 => {
let mut map = msp430::regclass_map();
msp430::fill_reg_map(arch, target_features, target, &mut map);
msp430::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
}
Expand Down Expand Up @@ -853,6 +857,7 @@ impl InlineAsmClobberAbi {
/// clobber ABIs for the target.
pub fn parse(
arch: InlineAsmArch,
reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
target: &Target,
name: Symbol,
Expand All @@ -878,7 +883,7 @@ impl InlineAsmClobberAbi {
},
InlineAsmArch::AArch64 => match name {
"C" | "system" | "efiapi" => {
Ok(if aarch64::reserved_x18(arch, target_features, target, true).is_err() {
Ok(if aarch64::reserved_x18(arch, reloc_model, target_features, target, true).is_err() {
InlineAsmClobberAbi::AArch64NoX18
} else {
InlineAsmClobberAbi::AArch64
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/asm/riscv.rs
@@ -1,5 +1,5 @@
use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target;
use crate::spec::{Target, RelocModel};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
Expand Down Expand Up @@ -54,6 +54,7 @@ impl RiscVInlineAsmRegClass {

fn not_e(
_arch: InlineAsmArch,
_reloc_model: RelocModel,
target_features: &FxHashSet<Symbol>,
_target: &Target,
_is_clobber: bool,
Expand Down

0 comments on commit 1ceb104

Please sign in to comment.