Fix handling of reserved registers for ARM inline asm
This commit is contained in:
parent
7adbc0dfef
commit
8d0e882065
6 changed files with 67 additions and 18 deletions
|
@ -1004,6 +1004,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
asm::InlineAsmReg::parse(
|
asm::InlineAsmReg::parse(
|
||||||
sess.asm_arch?,
|
sess.asm_arch?,
|
||||||
|feature| sess.target_features.contains(&Symbol::intern(feature)),
|
|feature| sess.target_features.contains(&Symbol::intern(feature)),
|
||||||
|
&sess.target.target,
|
||||||
s,
|
s,
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
|
|
@ -156,6 +156,10 @@ const ARM_WHITELIST: &[(&str, Option<Symbol>)] = &[
|
||||||
("vfp2", Some(sym::arm_target_feature)),
|
("vfp2", Some(sym::arm_target_feature)),
|
||||||
("vfp3", Some(sym::arm_target_feature)),
|
("vfp3", Some(sym::arm_target_feature)),
|
||||||
("vfp4", Some(sym::arm_target_feature)),
|
("vfp4", Some(sym::arm_target_feature)),
|
||||||
|
// This is needed for inline assembly, but shouldn't be stabilized as-is
|
||||||
|
// since it should be enabled per-function using #[instruction_set], not
|
||||||
|
// #[target_feature].
|
||||||
|
("thumb-mode", Some(sym::arm_target_feature)),
|
||||||
];
|
];
|
||||||
|
|
||||||
const AARCH64_WHITELIST: &[(&str, Option<Symbol>)] = &[
|
const AARCH64_WHITELIST: &[(&str, Option<Symbol>)] = &[
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{InlineAsmArch, InlineAsmType};
|
use super::{InlineAsmArch, InlineAsmType};
|
||||||
|
use crate::spec::Target;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -58,6 +59,37 @@ impl ArmInlineAsmRegClass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This uses the same logic as useR7AsFramePointer in LLVM
|
||||||
|
fn frame_pointer_is_r7(mut has_feature: impl FnMut(&str) -> bool, target: &Target) -> bool {
|
||||||
|
target.options.is_like_osx || (!target.options.is_like_windows && has_feature("thumb-mode"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame_pointer_r11(
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
has_feature: impl FnMut(&str) -> bool,
|
||||||
|
target: &Target,
|
||||||
|
_allocating: bool,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
|
if !frame_pointer_is_r7(has_feature, target) {
|
||||||
|
Err("the frame pointer (r11) cannot be used as an operand for inline asm")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame_pointer_r7(
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
has_feature: impl FnMut(&str) -> bool,
|
||||||
|
target: &Target,
|
||||||
|
_allocating: bool,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
|
if frame_pointer_is_r7(has_feature, target) {
|
||||||
|
Err("the frame pointer (r7) cannot be used as an operand for inline asm")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def_regs! {
|
def_regs! {
|
||||||
Arm ArmInlineAsmReg ArmInlineAsmRegClass {
|
Arm ArmInlineAsmReg ArmInlineAsmRegClass {
|
||||||
r0: reg, reg_thumb = ["r0", "a1"],
|
r0: reg, reg_thumb = ["r0", "a1"],
|
||||||
|
@ -66,11 +98,11 @@ def_regs! {
|
||||||
r3: reg, reg_thumb = ["r3", "a4"],
|
r3: reg, reg_thumb = ["r3", "a4"],
|
||||||
r4: reg, reg_thumb = ["r4", "v1"],
|
r4: reg, reg_thumb = ["r4", "v1"],
|
||||||
r5: reg, reg_thumb = ["r5", "v2"],
|
r5: reg, reg_thumb = ["r5", "v2"],
|
||||||
r6: reg, reg_thumb = ["r6", "v3"],
|
r7: reg, reg_thumb = ["r7", "v4"] % frame_pointer_r7,
|
||||||
r7: reg, reg_thumb = ["r7", "v4"],
|
|
||||||
r8: reg = ["r8", "v5"],
|
r8: reg = ["r8", "v5"],
|
||||||
r9: reg = ["r9", "v6", "rfp"],
|
r9: reg = ["r9", "v6", "rfp"],
|
||||||
r10: reg = ["r10", "sl"],
|
r10: reg = ["r10", "sl"],
|
||||||
|
r11: reg = ["r11", "fp"] % frame_pointer_r11,
|
||||||
r12: reg = ["r12", "ip"],
|
r12: reg = ["r12", "ip"],
|
||||||
r14: reg = ["r14", "lr"],
|
r14: reg = ["r14", "lr"],
|
||||||
s0: sreg, sreg_low16 = ["s0"],
|
s0: sreg, sreg_low16 = ["s0"],
|
||||||
|
@ -153,8 +185,8 @@ def_regs! {
|
||||||
q13: qreg = ["q13"],
|
q13: qreg = ["q13"],
|
||||||
q14: qreg = ["q14"],
|
q14: qreg = ["q14"],
|
||||||
q15: qreg = ["q15"],
|
q15: qreg = ["q15"],
|
||||||
#error = ["r11", "fp"] =>
|
#error = ["r6", "v3"] =>
|
||||||
"the frame pointer cannot be used as an operand for inline asm",
|
"r6 is used internally by LLVM and cannot be used as an operand for inline asm",
|
||||||
#error = ["r13", "sp"] =>
|
#error = ["r13", "sp"] =>
|
||||||
"the stack pointer cannot be used as an operand for inline asm",
|
"the stack pointer cannot be used as an operand for inline asm",
|
||||||
#error = ["r15", "pc"] =>
|
#error = ["r15", "pc"] =>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::abi::Size;
|
use crate::abi::Size;
|
||||||
|
use crate::spec::Target;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use rustc_span::Symbol;
|
use rustc_span::Symbol;
|
||||||
|
@ -83,12 +84,13 @@ macro_rules! def_regs {
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
_arch: super::InlineAsmArch,
|
_arch: super::InlineAsmArch,
|
||||||
mut _has_feature: impl FnMut(&str) -> bool,
|
mut _has_feature: impl FnMut(&str) -> bool,
|
||||||
|
_target: &crate::spec::Target,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<Self, &'static str> {
|
) -> Result<Self, &'static str> {
|
||||||
match name {
|
match name {
|
||||||
$(
|
$(
|
||||||
$($alias)|* | $reg_name => {
|
$($alias)|* | $reg_name => {
|
||||||
$($filter(_arch, &mut _has_feature, false)?;)?
|
$($filter(_arch, &mut _has_feature, _target, false)?;)?
|
||||||
Ok(Self::$reg)
|
Ok(Self::$reg)
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
@ -103,6 +105,7 @@ macro_rules! def_regs {
|
||||||
pub(super) fn fill_reg_map(
|
pub(super) fn fill_reg_map(
|
||||||
_arch: super::InlineAsmArch,
|
_arch: super::InlineAsmArch,
|
||||||
mut _has_feature: impl FnMut(&str) -> bool,
|
mut _has_feature: impl FnMut(&str) -> bool,
|
||||||
|
_target: &crate::spec::Target,
|
||||||
_map: &mut rustc_data_structures::fx::FxHashMap<
|
_map: &mut rustc_data_structures::fx::FxHashMap<
|
||||||
super::InlineAsmRegClass,
|
super::InlineAsmRegClass,
|
||||||
rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>,
|
rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>,
|
||||||
|
@ -111,7 +114,7 @@ macro_rules! def_regs {
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use super::{InlineAsmReg, InlineAsmRegClass};
|
use super::{InlineAsmReg, InlineAsmRegClass};
|
||||||
$(
|
$(
|
||||||
if $($filter(_arch, &mut _has_feature, true).is_ok() &&)? true {
|
if $($filter(_arch, &mut _has_feature, _target, true).is_ok() &&)? true {
|
||||||
if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
|
if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
|
||||||
set.insert(InlineAsmReg::$arch($arch_reg::$reg));
|
set.insert(InlineAsmReg::$arch($arch_reg::$reg));
|
||||||
}
|
}
|
||||||
|
@ -234,6 +237,7 @@ impl InlineAsmReg {
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
arch: InlineAsmArch,
|
arch: InlineAsmArch,
|
||||||
has_feature: impl FnMut(&str) -> bool,
|
has_feature: impl FnMut(&str) -> bool,
|
||||||
|
target: &Target,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
) -> Result<Self, &'static str> {
|
) -> Result<Self, &'static str> {
|
||||||
// FIXME: use direct symbol comparison for register names
|
// FIXME: use direct symbol comparison for register names
|
||||||
|
@ -241,20 +245,22 @@ impl InlineAsmReg {
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
Ok(match arch {
|
Ok(match arch {
|
||||||
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
|
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
|
||||||
Self::X86(X86InlineAsmReg::parse(arch, has_feature, &name)?)
|
Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
|
}
|
||||||
|
InlineAsmArch::Arm => {
|
||||||
|
Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, &name)?),
|
|
||||||
InlineAsmArch::AArch64 => {
|
InlineAsmArch::AArch64 => {
|
||||||
Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, &name)?)
|
Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
|
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
|
||||||
Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, &name)?)
|
Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::Nvptx64 => {
|
InlineAsmArch::Nvptx64 => {
|
||||||
Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, &name)?)
|
Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::Hexagon => {
|
InlineAsmArch::Hexagon => {
|
||||||
Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, &name)?)
|
Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -536,36 +542,37 @@ impl fmt::Display for InlineAsmType {
|
||||||
pub fn allocatable_registers(
|
pub fn allocatable_registers(
|
||||||
arch: InlineAsmArch,
|
arch: InlineAsmArch,
|
||||||
has_feature: impl FnMut(&str) -> bool,
|
has_feature: impl FnMut(&str) -> bool,
|
||||||
|
target: &crate::spec::Target,
|
||||||
) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
|
) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
|
||||||
match arch {
|
match arch {
|
||||||
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
|
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
|
||||||
let mut map = x86::regclass_map();
|
let mut map = x86::regclass_map();
|
||||||
x86::fill_reg_map(arch, has_feature, &mut map);
|
x86::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
InlineAsmArch::Arm => {
|
InlineAsmArch::Arm => {
|
||||||
let mut map = arm::regclass_map();
|
let mut map = arm::regclass_map();
|
||||||
arm::fill_reg_map(arch, has_feature, &mut map);
|
arm::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
InlineAsmArch::AArch64 => {
|
InlineAsmArch::AArch64 => {
|
||||||
let mut map = aarch64::regclass_map();
|
let mut map = aarch64::regclass_map();
|
||||||
aarch64::fill_reg_map(arch, has_feature, &mut map);
|
aarch64::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
|
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
|
||||||
let mut map = riscv::regclass_map();
|
let mut map = riscv::regclass_map();
|
||||||
riscv::fill_reg_map(arch, has_feature, &mut map);
|
riscv::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
InlineAsmArch::Nvptx64 => {
|
InlineAsmArch::Nvptx64 => {
|
||||||
let mut map = nvptx::regclass_map();
|
let mut map = nvptx::regclass_map();
|
||||||
nvptx::fill_reg_map(arch, has_feature, &mut map);
|
nvptx::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
InlineAsmArch::Hexagon => {
|
InlineAsmArch::Hexagon => {
|
||||||
let mut map = hexagon::regclass_map();
|
let mut map = hexagon::regclass_map();
|
||||||
hexagon::fill_reg_map(arch, has_feature, &mut map);
|
hexagon::fill_reg_map(arch, has_feature, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{InlineAsmArch, InlineAsmType};
|
use super::{InlineAsmArch, InlineAsmType};
|
||||||
|
use crate::spec::Target;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ impl RiscVInlineAsmRegClass {
|
||||||
fn not_e(
|
fn not_e(
|
||||||
_arch: InlineAsmArch,
|
_arch: InlineAsmArch,
|
||||||
mut has_feature: impl FnMut(&str) -> bool,
|
mut has_feature: impl FnMut(&str) -> bool,
|
||||||
|
_target: &Target,
|
||||||
_allocating: bool,
|
_allocating: bool,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
if has_feature("e") {
|
if has_feature("e") {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::{InlineAsmArch, InlineAsmType};
|
use super::{InlineAsmArch, InlineAsmType};
|
||||||
|
use crate::spec::Target;
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -131,6 +132,7 @@ impl X86InlineAsmRegClass {
|
||||||
fn x86_64_only(
|
fn x86_64_only(
|
||||||
arch: InlineAsmArch,
|
arch: InlineAsmArch,
|
||||||
_has_feature: impl FnMut(&str) -> bool,
|
_has_feature: impl FnMut(&str) -> bool,
|
||||||
|
_target: &Target,
|
||||||
_allocating: bool,
|
_allocating: bool,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
match arch {
|
match arch {
|
||||||
|
@ -143,6 +145,7 @@ fn x86_64_only(
|
||||||
fn high_byte(
|
fn high_byte(
|
||||||
arch: InlineAsmArch,
|
arch: InlineAsmArch,
|
||||||
_has_feature: impl FnMut(&str) -> bool,
|
_has_feature: impl FnMut(&str) -> bool,
|
||||||
|
_target: &Target,
|
||||||
allocating: bool,
|
allocating: bool,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
match arch {
|
match arch {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue