Skip to content

Commit cb35370

Browse files
authored
Rollup merge of #93877 - Amanieu:asm_fixes, r=nagisa
asm: Allow the use of r8-r14 as clobbers on Thumb1 Previously these were entirely disallowed, except for r11 which was allowed by accident. cc `@hudson-ayers`
2 parents 724cca6 + 11250b8 commit cb35370

File tree

7 files changed

+97
-46
lines changed

7 files changed

+97
-46
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
129129
.operands
130130
.iter()
131131
.map(|(op, op_sp)| {
132-
let lower_reg = |reg| match reg {
132+
let lower_reg = |reg, is_clobber| match reg {
133133
InlineAsmRegOrRegClass::Reg(s) => {
134134
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
135135
asm::InlineAsmReg::parse(
136136
asm_arch,
137137
&sess.target_features,
138138
&sess.target,
139+
is_clobber,
139140
s,
140141
)
141142
.unwrap_or_else(|e| {
@@ -162,24 +163,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
162163

163164
let op = match *op {
164165
InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
165-
reg: lower_reg(reg),
166+
reg: lower_reg(reg, false),
166167
expr: self.lower_expr_mut(expr),
167168
},
168169
InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
169-
reg: lower_reg(reg),
170+
reg: lower_reg(reg, expr.is_none()),
170171
late,
171172
expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
172173
},
173174
InlineAsmOperand::InOut { reg, late, ref expr } => {
174175
hir::InlineAsmOperand::InOut {
175-
reg: lower_reg(reg),
176+
reg: lower_reg(reg, false),
176177
late,
177178
expr: self.lower_expr_mut(expr),
178179
}
179180
}
180181
InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
181182
hir::InlineAsmOperand::SplitInOut {
182-
reg: lower_reg(reg),
183+
reg: lower_reg(reg, false),
183184
late,
184185
in_expr: self.lower_expr_mut(in_expr),
185186
out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),

compiler/rustc_target/src/asm/aarch64.rs

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub fn reserved_x18(
7777
_arch: InlineAsmArch,
7878
_target_features: &FxHashSet<Symbol>,
7979
target: &Target,
80+
_is_clobber: bool,
8081
) -> Result<(), &'static str> {
8182
if target.os == "android"
8283
|| target.is_like_fuchsia

compiler/rustc_target/src/asm/arm.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,13 @@ fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) ->
6666
}
6767

6868
fn frame_pointer_r11(
69-
_arch: InlineAsmArch,
69+
arch: InlineAsmArch,
7070
target_features: &FxHashSet<Symbol>,
7171
target: &Target,
72+
is_clobber: bool,
7273
) -> Result<(), &'static str> {
74+
not_thumb1(arch, target_features, target, is_clobber)?;
75+
7376
if !frame_pointer_is_r7(target_features, target) {
7477
Err("the frame pointer (r11) cannot be used as an operand for inline asm")
7578
} else {
@@ -81,6 +84,7 @@ fn frame_pointer_r7(
8184
_arch: InlineAsmArch,
8285
target_features: &FxHashSet<Symbol>,
8386
target: &Target,
87+
_is_clobber: bool,
8488
) -> Result<(), &'static str> {
8589
if frame_pointer_is_r7(target_features, target) {
8690
Err("the frame pointer (r7) cannot be used as an operand for inline asm")
@@ -93,9 +97,13 @@ fn not_thumb1(
9397
_arch: InlineAsmArch,
9498
target_features: &FxHashSet<Symbol>,
9599
_target: &Target,
100+
is_clobber: bool,
96101
) -> Result<(), &'static str> {
97-
if target_features.contains(&sym::thumb_mode) && !target_features.contains(&sym::thumb2) {
98-
Err("high registers (r8+) cannot be used in Thumb-1 code")
102+
if !is_clobber
103+
&& target_features.contains(&sym::thumb_mode)
104+
&& !target_features.contains(&sym::thumb2)
105+
{
106+
Err("high registers (r8+) can only be used as clobbers in Thumb-1 code")
99107
} else {
100108
Ok(())
101109
}
@@ -105,8 +113,9 @@ fn reserved_r9(
105113
arch: InlineAsmArch,
106114
target_features: &FxHashSet<Symbol>,
107115
target: &Target,
116+
is_clobber: bool,
108117
) -> Result<(), &'static str> {
109-
not_thumb1(arch, target_features, target)?;
118+
not_thumb1(arch, target_features, target, is_clobber)?;
110119

111120
// We detect this using the reserved-r9 feature instead of using the target
112121
// because the relocation model can be changed with compiler options.

compiler/rustc_target/src/asm/bpf.rs

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ fn only_alu32(
4747
_arch: InlineAsmArch,
4848
target_features: &FxHashSet<Symbol>,
4949
_target: &Target,
50+
_is_clobber: bool,
5051
) -> Result<(), &'static str> {
5152
if !target_features.contains(&sym::alu32) {
5253
Err("register can't be used without the `alu32` target feature")

compiler/rustc_target/src/asm/mod.rs

+71-37
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,13 @@ macro_rules! def_regs {
8383
_arch: super::InlineAsmArch,
8484
_target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
8585
_target: &crate::spec::Target,
86+
_is_clobber: bool,
8687
name: &str,
8788
) -> Result<Self, &'static str> {
8889
match name {
8990
$(
9091
$($alias)|* | $reg_name => {
91-
$($filter(_arch, _target_features, _target)?;)?
92+
$($filter(_arch, _target_features, _target, _is_clobber)?;)?
9293
Ok(Self::$reg)
9394
}
9495
)*
@@ -112,7 +113,7 @@ macro_rules! def_regs {
112113
#[allow(unused_imports)]
113114
use super::{InlineAsmReg, InlineAsmRegClass};
114115
$(
115-
if $($filter(_arch, _target_features, _target).is_ok() &&)? true {
116+
if $($filter(_arch, _target_features, _target, false).is_ok() &&)? true {
116117
if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
117118
set.insert(InlineAsmReg::$arch($arch_reg::$reg));
118119
}
@@ -298,54 +299,87 @@ impl InlineAsmReg {
298299
arch: InlineAsmArch,
299300
target_features: &FxHashSet<Symbol>,
300301
target: &Target,
302+
is_clobber: bool,
301303
name: Symbol,
302304
) -> Result<Self, &'static str> {
303305
// FIXME: use direct symbol comparison for register names
304306
// Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
305307
let name = name.as_str();
306308
Ok(match arch {
307309
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
308-
Self::X86(X86InlineAsmReg::parse(arch, target_features, target, name)?)
310+
Self::X86(X86InlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
309311
}
310312
InlineAsmArch::Arm => {
311-
Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, name)?)
312-
}
313-
InlineAsmArch::AArch64 => {
314-
Self::AArch64(AArch64InlineAsmReg::parse(arch, target_features, target, name)?)
315-
}
316-
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
317-
Self::RiscV(RiscVInlineAsmReg::parse(arch, target_features, target, name)?)
318-
}
319-
InlineAsmArch::Nvptx64 => {
320-
Self::Nvptx(NvptxInlineAsmReg::parse(arch, target_features, target, name)?)
321-
}
322-
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
323-
Self::PowerPC(PowerPCInlineAsmReg::parse(arch, target_features, target, name)?)
324-
}
325-
InlineAsmArch::Hexagon => {
326-
Self::Hexagon(HexagonInlineAsmReg::parse(arch, target_features, target, name)?)
327-
}
328-
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
329-
Self::Mips(MipsInlineAsmReg::parse(arch, target_features, target, name)?)
330-
}
331-
InlineAsmArch::S390x => {
332-
Self::S390x(S390xInlineAsmReg::parse(arch, target_features, target, name)?)
333-
}
334-
InlineAsmArch::SpirV => {
335-
Self::SpirV(SpirVInlineAsmReg::parse(arch, target_features, target, name)?)
336-
}
337-
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
338-
Self::Wasm(WasmInlineAsmReg::parse(arch, target_features, target, name)?)
313+
Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
339314
}
315+
InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(
316+
arch,
317+
target_features,
318+
target,
319+
is_clobber,
320+
name,
321+
)?),
322+
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => Self::RiscV(
323+
RiscVInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
324+
),
325+
InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(
326+
arch,
327+
target_features,
328+
target,
329+
is_clobber,
330+
name,
331+
)?),
332+
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => Self::PowerPC(
333+
PowerPCInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
334+
),
335+
InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(
336+
arch,
337+
target_features,
338+
target,
339+
is_clobber,
340+
name,
341+
)?),
342+
InlineAsmArch::Mips | InlineAsmArch::Mips64 => Self::Mips(MipsInlineAsmReg::parse(
343+
arch,
344+
target_features,
345+
target,
346+
is_clobber,
347+
name,
348+
)?),
349+
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(
350+
arch,
351+
target_features,
352+
target,
353+
is_clobber,
354+
name,
355+
)?),
356+
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(
357+
arch,
358+
target_features,
359+
target,
360+
is_clobber,
361+
name,
362+
)?),
363+
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => Self::Wasm(WasmInlineAsmReg::parse(
364+
arch,
365+
target_features,
366+
target,
367+
is_clobber,
368+
name,
369+
)?),
340370
InlineAsmArch::Bpf => {
341-
Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, name)?)
371+
Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
342372
}
343373
InlineAsmArch::Avr => {
344-
Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, name)?)
345-
}
346-
InlineAsmArch::Msp430 => {
347-
Self::Msp430(Msp430InlineAsmReg::parse(arch, target_features, target, name)?)
374+
Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
348375
}
376+
InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(
377+
arch,
378+
target_features,
379+
target,
380+
is_clobber,
381+
name,
382+
)?),
349383
})
350384
}
351385

@@ -844,7 +878,7 @@ impl InlineAsmClobberAbi {
844878
},
845879
InlineAsmArch::AArch64 => match name {
846880
"C" | "system" | "efiapi" => {
847-
Ok(if aarch64::reserved_x18(arch, target_features, target).is_err() {
881+
Ok(if aarch64::reserved_x18(arch, target_features, target, true).is_err() {
848882
InlineAsmClobberAbi::AArch64NoX18
849883
} else {
850884
InlineAsmClobberAbi::AArch64

compiler/rustc_target/src/asm/riscv.rs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ fn not_e(
5656
_arch: InlineAsmArch,
5757
target_features: &FxHashSet<Symbol>,
5858
_target: &Target,
59+
_is_clobber: bool,
5960
) -> Result<(), &'static str> {
6061
if target_features.contains(&sym::e) {
6162
Err("register can't be used with the `e` target feature")

compiler/rustc_target/src/asm/x86.rs

+4
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ fn x86_64_only(
141141
arch: InlineAsmArch,
142142
_target_features: &FxHashSet<Symbol>,
143143
_target: &Target,
144+
_is_clobber: bool,
144145
) -> Result<(), &'static str> {
145146
match arch {
146147
InlineAsmArch::X86 => Err("register is only available on x86_64"),
@@ -153,6 +154,7 @@ fn high_byte(
153154
arch: InlineAsmArch,
154155
_target_features: &FxHashSet<Symbol>,
155156
_target: &Target,
157+
_is_clobber: bool,
156158
) -> Result<(), &'static str> {
157159
match arch {
158160
InlineAsmArch::X86_64 => Err("high byte registers cannot be used as an operand on x86_64"),
@@ -164,6 +166,7 @@ fn rbx_reserved(
164166
arch: InlineAsmArch,
165167
_target_features: &FxHashSet<Symbol>,
166168
_target: &Target,
169+
_is_clobber: bool,
167170
) -> Result<(), &'static str> {
168171
match arch {
169172
InlineAsmArch::X86 => Ok(()),
@@ -178,6 +181,7 @@ fn esi_reserved(
178181
arch: InlineAsmArch,
179182
_target_features: &FxHashSet<Symbol>,
180183
_target: &Target,
184+
_is_clobber: bool,
181185
) -> Result<(), &'static str> {
182186
match arch {
183187
InlineAsmArch::X86 => {

0 commit comments

Comments
 (0)