Skip to content

Commit f927f15

Browse files
committed
Allow rustdoc to handle asm! of foreign architectures
1 parent 21cbbdc commit f927f15

File tree

4 files changed

+51
-2
lines changed

4 files changed

+51
-2
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -1242,14 +1242,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
12421242
}
12431243

12441244
fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
1245-
if self.sess.asm_arch.is_none() {
1245+
if self.sess.asm_arch.is_none() && !self.sess.opts.actually_rustdoc {
12461246
struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
12471247
}
12481248
if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
12491249
&& !matches!(
12501250
self.sess.asm_arch,
12511251
Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
12521252
)
1253+
&& !self.sess.opts.actually_rustdoc
12531254
{
12541255
self.sess
12551256
.struct_span_err(sp, "the `att_syntax` option is only supported on x86")
@@ -1265,6 +1266,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
12651266
.filter_map(|(op, op_sp)| {
12661267
let lower_reg = |reg| {
12671268
Some(match reg {
1269+
InlineAsmRegOrRegClass::Reg(_) if sess.opts.actually_rustdoc => {
1270+
asm::InlineAsmRegOrRegClass::Reg(asm::InlineAsmReg::RustdocDummy)
1271+
}
1272+
InlineAsmRegOrRegClass::RegClass(_) if sess.opts.actually_rustdoc => {
1273+
asm::InlineAsmRegOrRegClass::RegClass(
1274+
asm::InlineAsmRegClass::RustdocDummy,
1275+
)
1276+
}
12681277
InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
12691278
asm::InlineAsmReg::parse(
12701279
sess.asm_arch?,
@@ -1355,7 +1364,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
13551364
| hir::InlineAsmOperand::SplitInOut { reg, .. } => {
13561365
let class = reg.reg_class();
13571366
let valid_modifiers = class.valid_modifiers(asm_arch);
1358-
if !valid_modifiers.contains(&modifier) {
1367+
if !valid_modifiers.contains(&modifier) && !self.sess.opts.actually_rustdoc
1368+
{
13591369
let mut err = sess.struct_span_err(
13601370
placeholder_span,
13611371
"invalid asm template modifier for this register class",

compiler/rustc_codegen_llvm/src/asm.rs

+3
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
524524
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
525525
bug!("LLVM backend does not support SPIR-V")
526526
}
527+
InlineAsmRegClass::RustdocDummy => unreachable!(),
527528
}
528529
.to_string(),
529530
}
@@ -590,6 +591,7 @@ fn modifier_to_llvm(
590591
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
591592
bug!("LLVM backend does not support SPIR-V")
592593
}
594+
InlineAsmRegClass::RustdocDummy => unreachable!(),
593595
}
594596
}
595597

@@ -633,6 +635,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
633635
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
634636
bug!("LLVM backend does not support SPIR-V")
635637
}
638+
InlineAsmRegClass::RustdocDummy => unreachable!(),
636639
}
637640
}
638641

compiler/rustc_target/src/asm/mod.rs

+20
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ pub enum InlineAsmReg {
218218
Mips(MipsInlineAsmReg),
219219
SpirV(SpirVInlineAsmReg),
220220
Wasm(WasmInlineAsmReg),
221+
// Fake register used by rustdoc to support foreign asm!
222+
RustdocDummy,
221223
}
222224

223225
impl InlineAsmReg {
@@ -229,6 +231,7 @@ impl InlineAsmReg {
229231
Self::RiscV(r) => r.name(),
230232
Self::Hexagon(r) => r.name(),
231233
Self::Mips(r) => r.name(),
234+
Self::RustdocDummy => "<reg>",
232235
}
233236
}
234237

@@ -240,6 +243,7 @@ impl InlineAsmReg {
240243
Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()),
241244
Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
242245
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
246+
Self::RustdocDummy => InlineAsmRegClass::RustdocDummy,
243247
}
244248
}
245249

@@ -298,6 +302,7 @@ impl InlineAsmReg {
298302
Self::RiscV(r) => r.emit(out, arch, modifier),
299303
Self::Hexagon(r) => r.emit(out, arch, modifier),
300304
Self::Mips(r) => r.emit(out, arch, modifier),
305+
Self::RustdocDummy => unreachable!(),
301306
}
302307
}
303308

@@ -309,6 +314,10 @@ impl InlineAsmReg {
309314
Self::RiscV(_) => cb(self),
310315
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
311316
Self::Mips(_) => cb(self),
317+
Self::RustdocDummy => {
318+
// This effectively disables the register conflict check since
319+
// we don't report RustdocDummy as conflicting with itself.
320+
}
312321
}
313322
}
314323
}
@@ -324,6 +333,8 @@ pub enum InlineAsmRegClass {
324333
Mips(MipsInlineAsmRegClass),
325334
SpirV(SpirVInlineAsmRegClass),
326335
Wasm(WasmInlineAsmRegClass),
336+
// Fake register class used by rustdoc to support foreign asm!
337+
RustdocDummy,
327338
}
328339

329340
impl InlineAsmRegClass {
@@ -338,6 +349,7 @@ impl InlineAsmRegClass {
338349
Self::Mips(r) => r.name(),
339350
Self::SpirV(r) => r.name(),
340351
Self::Wasm(r) => r.name(),
352+
Self::RustdocDummy => rustc_span::symbol::sym::reg,
341353
}
342354
}
343355

@@ -355,6 +367,7 @@ impl InlineAsmRegClass {
355367
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
356368
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
357369
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
370+
Self::RustdocDummy => None,
358371
}
359372
}
360373

@@ -379,6 +392,7 @@ impl InlineAsmRegClass {
379392
Self::Mips(r) => r.suggest_modifier(arch, ty),
380393
Self::SpirV(r) => r.suggest_modifier(arch, ty),
381394
Self::Wasm(r) => r.suggest_modifier(arch, ty),
395+
Self::RustdocDummy => None,
382396
}
383397
}
384398

@@ -399,6 +413,7 @@ impl InlineAsmRegClass {
399413
Self::Mips(r) => r.default_modifier(arch),
400414
Self::SpirV(r) => r.default_modifier(arch),
401415
Self::Wasm(r) => r.default_modifier(arch),
416+
Self::RustdocDummy => None,
402417
}
403418
}
404419

@@ -418,6 +433,9 @@ impl InlineAsmRegClass {
418433
Self::Mips(r) => r.supported_types(arch),
419434
Self::SpirV(r) => r.supported_types(arch),
420435
Self::Wasm(r) => r.supported_types(arch),
436+
// Rustdoc never gets around to type-checking the asm!, this is just
437+
// used to indicate the lack of any dependency on target features.
438+
Self::RustdocDummy => &[],
421439
}
422440
}
423441

@@ -454,6 +472,8 @@ impl InlineAsmRegClass {
454472
Self::Mips(r) => r.valid_modifiers(arch),
455473
Self::SpirV(r) => r.valid_modifiers(arch),
456474
Self::Wasm(r) => r.valid_modifiers(arch),
475+
// The modifier check is skipped in the code for rustdoc
476+
Self::RustdocDummy => &[],
457477
}
458478
}
459479
}

src/test/rustdoc-ui/asm-foreign.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
// Make sure rustdoc accepts asm! for a foreign architecture.
3+
4+
#![feature(asm)]
5+
6+
pub unsafe fn aarch64(a: f64, b: f64) {
7+
let c;
8+
asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") b);
9+
c
10+
}
11+
12+
pub unsafe fn x86(a: f64, b: f64) {
13+
let c;
14+
asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
15+
c
16+
}

0 commit comments

Comments
 (0)