Skip to content

Commit 1cf2e69

Browse files
authored
Rollup merge of #94169 - Amanieu:asm_stuff, r=nagisa
Fix several asm! related issues This is a combination of several fixes, each split into a separate commit. Splitting these into PRs is not practical since they conflict with each other. Fixes #92378 Fixes #85247 r? ``@nagisa``
2 parents 58a721a + a60b791 commit 1cf2e69

File tree

18 files changed

+292
-237
lines changed

18 files changed

+292
-237
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+7-19
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
6464
let mut clobber_abis = FxHashMap::default();
6565
if let Some(asm_arch) = asm_arch {
6666
for (abi_name, abi_span) in &asm.clobber_abis {
67-
match asm::InlineAsmClobberAbi::parse(
68-
asm_arch,
69-
&self.sess.target_features,
70-
&self.sess.target,
71-
*abi_name,
72-
) {
67+
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) {
7368
Ok(abi) => {
7469
// If the abi was already in the list, emit an error
7570
match clobber_abis.get(&abi) {
@@ -129,17 +124,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
129124
.operands
130125
.iter()
131126
.map(|(op, op_sp)| {
132-
let lower_reg = |reg, is_clobber| match reg {
127+
let lower_reg = |reg| match reg {
133128
InlineAsmRegOrRegClass::Reg(s) => {
134129
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
135-
asm::InlineAsmReg::parse(
136-
asm_arch,
137-
&sess.target_features,
138-
&sess.target,
139-
is_clobber,
140-
s,
141-
)
142-
.unwrap_or_else(|e| {
130+
asm::InlineAsmReg::parse(asm_arch, s).unwrap_or_else(|e| {
143131
let msg = format!("invalid register `{}`: {}", s.as_str(), e);
144132
sess.struct_span_err(*op_sp, &msg).emit();
145133
asm::InlineAsmReg::Err
@@ -163,24 +151,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
163151

164152
let op = match *op {
165153
InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
166-
reg: lower_reg(reg, false),
154+
reg: lower_reg(reg),
167155
expr: self.lower_expr_mut(expr),
168156
},
169157
InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
170-
reg: lower_reg(reg, expr.is_none()),
158+
reg: lower_reg(reg),
171159
late,
172160
expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
173161
},
174162
InlineAsmOperand::InOut { reg, late, ref expr } => {
175163
hir::InlineAsmOperand::InOut {
176-
reg: lower_reg(reg, false),
164+
reg: lower_reg(reg),
177165
late,
178166
expr: self.lower_expr_mut(expr),
179167
}
180168
}
181169
InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
182170
hir::InlineAsmOperand::SplitInOut {
183-
reg: lower_reg(reg, false),
171+
reg: lower_reg(reg),
184172
late,
185173
in_expr: self.lower_expr_mut(in_expr),
186174
out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),

compiler/rustc_codegen_cranelift/src/inline_asm.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
106106
let mut asm_gen = InlineAssemblyGenerator {
107107
tcx: fx.tcx,
108108
arch: fx.tcx.sess.asm_arch.unwrap(),
109+
enclosing_def_id: fx.instance.def_id(),
109110
template,
110111
operands,
111112
options,
@@ -169,6 +170,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
169170
struct InlineAssemblyGenerator<'a, 'tcx> {
170171
tcx: TyCtxt<'tcx>,
171172
arch: InlineAsmArch,
173+
enclosing_def_id: DefId,
172174
template: &'a [InlineAsmTemplatePiece],
173175
operands: &'a [InlineAsmOperand<'tcx>],
174176
options: InlineAsmOptions,
@@ -182,7 +184,12 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
182184
impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
183185
fn allocate_registers(&mut self) {
184186
let sess = self.tcx.sess;
185-
let map = allocatable_registers(self.arch, &sess.target_features, &sess.target);
187+
let map = allocatable_registers(
188+
self.arch,
189+
sess.relocation_model(),
190+
self.tcx.asm_target_features(self.enclosing_def_id),
191+
&sess.target,
192+
);
186193
let mut allocated = FxHashMap::<_, (bool, bool)>::default();
187194
let mut regs = vec![None; self.operands.len()];
188195

@@ -313,14 +320,9 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
313320
let mut new_slot = |x| new_slot_fn(&mut slot_size, x);
314321

315322
// Allocate stack slots for saving clobbered registers
316-
let abi_clobber = InlineAsmClobberAbi::parse(
317-
self.arch,
318-
&self.tcx.sess.target_features,
319-
&self.tcx.sess.target,
320-
sym::C,
321-
)
322-
.unwrap()
323-
.clobbered_regs();
323+
let abi_clobber = InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, sym::C)
324+
.unwrap()
325+
.clobbered_regs();
324326
for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) {
325327
let mut need_save = true;
326328
// If the register overlaps with a register clobbered by function call, then

compiler/rustc_codegen_ssa/src/target_features.rs

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
3636
// #[target_feature].
3737
("thumb-mode", Some(sym::arm_target_feature)),
3838
("thumb2", Some(sym::arm_target_feature)),
39-
("reserve-r9", Some(sym::arm_target_feature)),
4039
];
4140

4241
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[

compiler/rustc_middle/src/query/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,10 @@ rustc_queries! {
10461046
cache_on_disk_if { true }
10471047
}
10481048

1049+
query asm_target_features(def_id: DefId) -> &'tcx FxHashSet<Symbol> {
1050+
desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
1051+
}
1052+
10491053
query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] {
10501054
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
10511055
separate_provide_extern

compiler/rustc_passes/src/intrinsicck.rs

+28-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_ast::InlineAsmTemplatePiece;
2+
use rustc_data_structures::stable_set::FxHashSet;
23
use rustc_errors::struct_span_err;
34
use rustc_hir as hir;
45
use rustc_hir::def::{DefKind, Res};
@@ -138,7 +139,7 @@ impl<'tcx> ExprVisitor<'tcx> {
138139
template: &[InlineAsmTemplatePiece],
139140
is_input: bool,
140141
tied_input: Option<(&hir::Expr<'tcx>, Option<InlineAsmType>)>,
141-
target_features: &[Symbol],
142+
target_features: &FxHashSet<Symbol>,
142143
) -> Option<InlineAsmType> {
143144
// Check the type against the allowed types for inline asm.
144145
let ty = self.typeck_results.expr_ty_adjusted(expr);
@@ -285,9 +286,7 @@ impl<'tcx> ExprVisitor<'tcx> {
285286
// (!). In that case we still need the earlier check to verify that the
286287
// register class is usable at all.
287288
if let Some(feature) = feature {
288-
if !self.tcx.sess.target_features.contains(&feature)
289-
&& !target_features.contains(&feature)
290-
{
289+
if !target_features.contains(&feature) {
291290
let msg = &format!("`{}` target feature is not enabled", feature);
292291
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
293292
err.note(&format!(
@@ -347,7 +346,8 @@ impl<'tcx> ExprVisitor<'tcx> {
347346
let hir = self.tcx.hir();
348347
let enclosing_id = hir.enclosing_body_owner(hir_id);
349348
let enclosing_def_id = hir.local_def_id(enclosing_id).to_def_id();
350-
let attrs = self.tcx.codegen_fn_attrs(enclosing_def_id);
349+
let target_features = self.tcx.asm_target_features(enclosing_def_id);
350+
let asm_arch = self.tcx.sess.asm_arch.unwrap();
351351
for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
352352
// Validate register classes against currently enabled target
353353
// features. We check that at least one type is available for
@@ -360,16 +360,29 @@ impl<'tcx> ExprVisitor<'tcx> {
360360
// Note that this is only possible for explicit register
361361
// operands, which cannot be used in the asm string.
362362
if let Some(reg) = op.reg() {
363+
// Some explicit registers cannot be used depending on the
364+
// target. Reject those here.
365+
if let InlineAsmRegOrRegClass::Reg(reg) = reg {
366+
if let Err(msg) = reg.validate(
367+
asm_arch,
368+
self.tcx.sess.relocation_model(),
369+
&target_features,
370+
&self.tcx.sess.target,
371+
op.is_clobber(),
372+
) {
373+
let msg = format!("cannot use register `{}`: {}", reg.name(), msg);
374+
self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
375+
continue;
376+
}
377+
}
378+
363379
if !op.is_clobber() {
364380
let mut missing_required_features = vec![];
365381
let reg_class = reg.reg_class();
366-
for &(_, feature) in reg_class.supported_types(self.tcx.sess.asm_arch.unwrap())
367-
{
382+
for &(_, feature) in reg_class.supported_types(asm_arch) {
368383
match feature {
369384
Some(feature) => {
370-
if self.tcx.sess.target_features.contains(&feature)
371-
|| attrs.target_features.contains(&feature)
372-
{
385+
if target_features.contains(&feature) {
373386
missing_required_features.clear();
374387
break;
375388
} else {
@@ -425,7 +438,7 @@ impl<'tcx> ExprVisitor<'tcx> {
425438
asm.template,
426439
true,
427440
None,
428-
&attrs.target_features,
441+
&target_features,
429442
);
430443
}
431444
hir::InlineAsmOperand::Out { reg, late: _, ref expr } => {
@@ -437,7 +450,7 @@ impl<'tcx> ExprVisitor<'tcx> {
437450
asm.template,
438451
false,
439452
None,
440-
&attrs.target_features,
453+
&target_features,
441454
);
442455
}
443456
}
@@ -449,7 +462,7 @@ impl<'tcx> ExprVisitor<'tcx> {
449462
asm.template,
450463
false,
451464
None,
452-
&attrs.target_features,
465+
&target_features,
453466
);
454467
}
455468
hir::InlineAsmOperand::SplitInOut { reg, late: _, ref in_expr, ref out_expr } => {
@@ -460,7 +473,7 @@ impl<'tcx> ExprVisitor<'tcx> {
460473
asm.template,
461474
true,
462475
None,
463-
&attrs.target_features,
476+
&target_features,
464477
);
465478
if let Some(out_expr) = out_expr {
466479
self.check_asm_operand_type(
@@ -470,7 +483,7 @@ impl<'tcx> ExprVisitor<'tcx> {
470483
asm.template,
471484
false,
472485
Some((in_expr, in_ty)),
473-
&attrs.target_features,
486+
&target_features,
474487
);
475488
}
476489
}

compiler/rustc_span/src/symbol.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,6 @@ symbols! {
11221122
repr_packed,
11231123
repr_simd,
11241124
repr_transparent,
1125-
reserved_r9: "reserved-r9",
11261125
residual,
11271126
result,
11281127
rhs,

compiler/rustc_target/src/asm/aarch64.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{InlineAsmArch, InlineAsmType};
2-
use crate::spec::Target;
2+
use crate::spec::{RelocModel, Target};
33
use rustc_data_structures::stable_set::FxHashSet;
44
use rustc_macros::HashStable_Generic;
55
use rustc_span::Symbol;
@@ -73,17 +73,18 @@ impl AArch64InlineAsmRegClass {
7373
}
7474
}
7575

76-
pub fn reserved_x18(
76+
pub fn target_reserves_x18(target: &Target) -> bool {
77+
target.os == "android" || target.is_like_fuchsia || target.is_like_osx || target.is_like_windows
78+
}
79+
80+
fn reserved_x18(
7781
_arch: InlineAsmArch,
82+
_reloc_model: RelocModel,
7883
_target_features: &FxHashSet<Symbol>,
7984
target: &Target,
8085
_is_clobber: bool,
8186
) -> Result<(), &'static str> {
82-
if target.os == "android"
83-
|| target.is_like_fuchsia
84-
|| target.is_like_osx
85-
|| target.is_like_windows
86-
{
87+
if target_reserves_x18(target) {
8788
Err("x18 is a reserved register on this target")
8889
} else {
8990
Ok(())

compiler/rustc_target/src/asm/arm.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{InlineAsmArch, InlineAsmType};
2-
use crate::spec::Target;
2+
use crate::spec::{RelocModel, Target};
33
use rustc_data_structures::stable_set::FxHashSet;
44
use rustc_macros::HashStable_Generic;
55
use rustc_span::{sym, Symbol};
@@ -67,11 +67,12 @@ fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) ->
6767

6868
fn frame_pointer_r11(
6969
arch: InlineAsmArch,
70+
reloc_model: RelocModel,
7071
target_features: &FxHashSet<Symbol>,
7172
target: &Target,
7273
is_clobber: bool,
7374
) -> Result<(), &'static str> {
74-
not_thumb1(arch, target_features, target, is_clobber)?;
75+
not_thumb1(arch, reloc_model, target_features, target, is_clobber)?;
7576

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

8384
fn frame_pointer_r7(
8485
_arch: InlineAsmArch,
86+
_reloc_model: RelocModel,
8587
target_features: &FxHashSet<Symbol>,
8688
target: &Target,
8789
_is_clobber: bool,
@@ -95,6 +97,7 @@ fn frame_pointer_r7(
9597

9698
fn not_thumb1(
9799
_arch: InlineAsmArch,
100+
_reloc_model: RelocModel,
98101
target_features: &FxHashSet<Symbol>,
99102
_target: &Target,
100103
is_clobber: bool,
@@ -111,18 +114,18 @@ fn not_thumb1(
111114

112115
fn reserved_r9(
113116
arch: InlineAsmArch,
117+
reloc_model: RelocModel,
114118
target_features: &FxHashSet<Symbol>,
115119
target: &Target,
116120
is_clobber: bool,
117121
) -> Result<(), &'static str> {
118-
not_thumb1(arch, target_features, target, is_clobber)?;
122+
not_thumb1(arch, reloc_model, target_features, target, is_clobber)?;
119123

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

0 commit comments

Comments
 (0)