Skip to content

Commit

Permalink
Allow rustdoc to handle asm! of foreign architectures
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu committed Mar 6, 2021
1 parent 21cbbdc commit f927f15
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
14 changes: 12 additions & 2 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,14 +1242,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
if self.sess.asm_arch.is_none() {
if self.sess.asm_arch.is_none() && !self.sess.opts.actually_rustdoc {
struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
}
if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
&& !matches!(
self.sess.asm_arch,
Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
)
&& !self.sess.opts.actually_rustdoc
{
self.sess
.struct_span_err(sp, "the `att_syntax` option is only supported on x86")
Expand All @@ -1265,6 +1266,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
.filter_map(|(op, op_sp)| {
let lower_reg = |reg| {
Some(match reg {
InlineAsmRegOrRegClass::Reg(_) if sess.opts.actually_rustdoc => {
asm::InlineAsmRegOrRegClass::Reg(asm::InlineAsmReg::RustdocDummy)
}
InlineAsmRegOrRegClass::RegClass(_) if sess.opts.actually_rustdoc => {
asm::InlineAsmRegOrRegClass::RegClass(
asm::InlineAsmRegClass::RustdocDummy,
)
}
InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
asm::InlineAsmReg::parse(
sess.asm_arch?,
Expand Down Expand Up @@ -1355,7 +1364,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
| hir::InlineAsmOperand::SplitInOut { reg, .. } => {
let class = reg.reg_class();
let valid_modifiers = class.valid_modifiers(asm_arch);
if !valid_modifiers.contains(&modifier) {
if !valid_modifiers.contains(&modifier) && !self.sess.opts.actually_rustdoc
{
let mut err = sess.struct_span_err(
placeholder_span,
"invalid asm template modifier for this register class",
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
InlineAsmRegClass::RustdocDummy => unreachable!(),
}
.to_string(),
}
Expand Down Expand Up @@ -590,6 +591,7 @@ fn modifier_to_llvm(
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
InlineAsmRegClass::RustdocDummy => unreachable!(),
}
}

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

Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_target/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ pub enum InlineAsmReg {
Mips(MipsInlineAsmReg),
SpirV(SpirVInlineAsmReg),
Wasm(WasmInlineAsmReg),
// Fake register used by rustdoc to support foreign asm!
RustdocDummy,
}

impl InlineAsmReg {
Expand All @@ -229,6 +231,7 @@ impl InlineAsmReg {
Self::RiscV(r) => r.name(),
Self::Hexagon(r) => r.name(),
Self::Mips(r) => r.name(),
Self::RustdocDummy => "<reg>",
}
}

Expand All @@ -240,6 +243,7 @@ impl InlineAsmReg {
Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()),
Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
Self::RustdocDummy => InlineAsmRegClass::RustdocDummy,
}
}

Expand Down Expand Up @@ -298,6 +302,7 @@ impl InlineAsmReg {
Self::RiscV(r) => r.emit(out, arch, modifier),
Self::Hexagon(r) => r.emit(out, arch, modifier),
Self::Mips(r) => r.emit(out, arch, modifier),
Self::RustdocDummy => unreachable!(),
}
}

Expand All @@ -309,6 +314,10 @@ impl InlineAsmReg {
Self::RiscV(_) => cb(self),
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
Self::Mips(_) => cb(self),
Self::RustdocDummy => {
// This effectively disables the register conflict check since
// we don't report RustdocDummy as conflicting with itself.
}
}
}
}
Expand All @@ -324,6 +333,8 @@ pub enum InlineAsmRegClass {
Mips(MipsInlineAsmRegClass),
SpirV(SpirVInlineAsmRegClass),
Wasm(WasmInlineAsmRegClass),
// Fake register class used by rustdoc to support foreign asm!
RustdocDummy,
}

impl InlineAsmRegClass {
Expand All @@ -338,6 +349,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.name(),
Self::SpirV(r) => r.name(),
Self::Wasm(r) => r.name(),
Self::RustdocDummy => rustc_span::symbol::sym::reg,
}
}

Expand All @@ -355,6 +367,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
Self::RustdocDummy => None,
}
}

Expand All @@ -379,6 +392,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.suggest_modifier(arch, ty),
Self::SpirV(r) => r.suggest_modifier(arch, ty),
Self::Wasm(r) => r.suggest_modifier(arch, ty),
Self::RustdocDummy => None,
}
}

Expand All @@ -399,6 +413,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.default_modifier(arch),
Self::SpirV(r) => r.default_modifier(arch),
Self::Wasm(r) => r.default_modifier(arch),
Self::RustdocDummy => None,
}
}

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

Expand Down Expand Up @@ -454,6 +472,8 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.valid_modifiers(arch),
Self::SpirV(r) => r.valid_modifiers(arch),
Self::Wasm(r) => r.valid_modifiers(arch),
// The modifier check is skipped in the code for rustdoc
Self::RustdocDummy => &[],
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/test/rustdoc-ui/asm-foreign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// check-pass
// Make sure rustdoc accepts asm! for a foreign architecture.

#![feature(asm)]

pub unsafe fn aarch64(a: f64, b: f64) {
let c;
asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") b);
c
}

pub unsafe fn x86(a: f64, b: f64) {
let c;
asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
c
}

0 comments on commit f927f15

Please sign in to comment.