mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
various fixes for naked_asm!
implementation
- fix for divergence - fix error message - fix another cranelift test - fix some cranelift things - don't set the NORETURN option for naked asm - fix use of naked_asm! in doc comment - fix use of naked_asm! in run-make test - use `span_bug` in unreachable branch
This commit is contained in:
parent
10fa482906
commit
5fc60d1e52
@ -2435,7 +2435,7 @@ pub enum AsmMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AsmMacro {
|
impl AsmMacro {
|
||||||
pub const fn macro_name(&self) -> &'static str {
|
pub const fn macro_name(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
AsmMacro::Asm => "asm",
|
AsmMacro::Asm => "asm",
|
||||||
AsmMacro::GlobalAsm => "global_asm",
|
AsmMacro::GlobalAsm => "global_asm",
|
||||||
@ -2443,13 +2443,21 @@ impl AsmMacro {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn is_supported_option(&self, option: InlineAsmOptions) -> bool {
|
pub const fn is_supported_option(self, option: InlineAsmOptions) -> bool {
|
||||||
match self {
|
match self {
|
||||||
AsmMacro::Asm => true,
|
AsmMacro::Asm => true,
|
||||||
AsmMacro::GlobalAsm => InlineAsmOptions::GLOBAL_OPTIONS.contains(option),
|
AsmMacro::GlobalAsm => InlineAsmOptions::GLOBAL_OPTIONS.contains(option),
|
||||||
AsmMacro::NakedAsm => InlineAsmOptions::NAKED_OPTIONS.contains(option),
|
AsmMacro::NakedAsm => InlineAsmOptions::NAKED_OPTIONS.contains(option),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn diverges(self, options: InlineAsmOptions) -> bool {
|
||||||
|
match self {
|
||||||
|
AsmMacro::Asm => options.contains(InlineAsmOptions::NORETURN),
|
||||||
|
AsmMacro::GlobalAsm => true,
|
||||||
|
AsmMacro::NakedAsm => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inline assembly.
|
/// Inline assembly.
|
||||||
|
@ -742,6 +742,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminatorKind::InlineAsm {
|
TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template: _,
|
template: _,
|
||||||
operands,
|
operands,
|
||||||
options: _,
|
options: _,
|
||||||
|
@ -169,6 +169,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TerminatorKind::InlineAsm {
|
TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template: _,
|
template: _,
|
||||||
operands,
|
operands,
|
||||||
options: _,
|
options: _,
|
||||||
|
@ -850,22 +850,13 @@ pub(super) fn expand_naked_asm<'cx>(
|
|||||||
return ExpandResult::Retry(());
|
return ExpandResult::Retry(());
|
||||||
};
|
};
|
||||||
let expr = match mac {
|
let expr = match mac {
|
||||||
Ok(mut inline_asm) => {
|
Ok(inline_asm) => P(ast::Expr {
|
||||||
// for future compatibility, we always set the NORETURN option.
|
|
||||||
//
|
|
||||||
// When we turn `asm!` into `naked_asm!` with this implementation, we can drop
|
|
||||||
// the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!`
|
|
||||||
// starts disallowing the `noreturn` option in the future
|
|
||||||
inline_asm.options |= ast::InlineAsmOptions::NORETURN;
|
|
||||||
|
|
||||||
P(ast::Expr {
|
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
|
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
|
||||||
span: sp,
|
span: sp,
|
||||||
attrs: ast::AttrVec::new(),
|
attrs: ast::AttrVec::new(),
|
||||||
tokens: None,
|
tokens: None,
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
Err(guar) => DummyResult::raw_expr(sp, Some(guar)),
|
Err(guar) => DummyResult::raw_expr(sp, Some(guar)),
|
||||||
};
|
};
|
||||||
MacEager::expr(expr)
|
MacEager::expr(expr)
|
||||||
|
@ -726,6 +726,12 @@ pub macro global_asm() {
|
|||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
|
pub macro naked_asm() {
|
||||||
|
/* compiler built-in */
|
||||||
|
}
|
||||||
|
|
||||||
pub static A_STATIC: u8 = 42;
|
pub static A_STATIC: u8 = 42;
|
||||||
|
|
||||||
#[lang = "panic_location"]
|
#[lang = "panic_location"]
|
||||||
|
@ -390,7 +390,7 @@ global_asm! {
|
|||||||
#[naked]
|
#[naked]
|
||||||
extern "C" fn naked_test() {
|
extern "C" fn naked_test() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("ret", options(noreturn));
|
naked_asm!("ret");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use rustc_ast::InlineAsmOptions;
|
|||||||
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
|
use rustc_middle::mir::InlineAsmMacro;
|
||||||
use rustc_middle::ty::TypeVisitableExt;
|
use rustc_middle::ty::TypeVisitableExt;
|
||||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||||
use rustc_middle::ty::layout::FnAbiOf;
|
use rustc_middle::ty::layout::FnAbiOf;
|
||||||
@ -57,6 +58,7 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||||||
|
|
||||||
match &mir.basic_blocks[START_BLOCK].terminator().kind {
|
match &mir.basic_blocks[START_BLOCK].terminator().kind {
|
||||||
TerminatorKind::InlineAsm {
|
TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: InlineAsmMacro::NakedAsm,
|
||||||
template,
|
template,
|
||||||
operands,
|
operands,
|
||||||
options,
|
options,
|
||||||
@ -498,6 +500,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
|||||||
"tail calls are not yet supported in `rustc_codegen_cranelift` backend"
|
"tail calls are not yet supported in `rustc_codegen_cranelift` backend"
|
||||||
),
|
),
|
||||||
TerminatorKind::InlineAsm {
|
TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template,
|
template,
|
||||||
operands,
|
operands,
|
||||||
options,
|
options,
|
||||||
|
@ -3,7 +3,9 @@ use std::cmp;
|
|||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_middle::mir::{self, AssertKind, BasicBlock, SwitchTargets, UnwindTerminateReason};
|
use rustc_middle::mir::{
|
||||||
|
self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason,
|
||||||
|
};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::{self, Instance, Ty};
|
use rustc_middle::ty::{self, Instance, Ty};
|
||||||
@ -1133,6 +1135,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
helper: TerminatorCodegenHelper<'tcx>,
|
helper: TerminatorCodegenHelper<'tcx>,
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
|
asm_macro: InlineAsmMacro,
|
||||||
terminator: &mir::Terminator<'tcx>,
|
terminator: &mir::Terminator<'tcx>,
|
||||||
template: &[ast::InlineAsmTemplatePiece],
|
template: &[ast::InlineAsmTemplatePiece],
|
||||||
operands: &[mir::InlineAsmOperand<'tcx>],
|
operands: &[mir::InlineAsmOperand<'tcx>],
|
||||||
@ -1203,11 +1206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
&operands,
|
&operands,
|
||||||
options,
|
options,
|
||||||
line_spans,
|
line_spans,
|
||||||
if options.contains(InlineAsmOptions::NORETURN) {
|
if asm_macro.diverges(options) { None } else { targets.get(0).copied() },
|
||||||
None
|
|
||||||
} else {
|
|
||||||
targets.get(0).copied()
|
|
||||||
},
|
|
||||||
unwind,
|
unwind,
|
||||||
instance,
|
instance,
|
||||||
mergeable_succ,
|
mergeable_succ,
|
||||||
@ -1381,6 +1380,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mir::TerminatorKind::InlineAsm {
|
mir::TerminatorKind::InlineAsm {
|
||||||
|
asm_macro,
|
||||||
template,
|
template,
|
||||||
ref operands,
|
ref operands,
|
||||||
options,
|
options,
|
||||||
@ -1390,6 +1390,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
} => self.codegen_asm_terminator(
|
} => self.codegen_asm_terminator(
|
||||||
helper,
|
helper,
|
||||||
bx,
|
bx,
|
||||||
|
asm_macro,
|
||||||
terminator,
|
terminator,
|
||||||
template,
|
template,
|
||||||
operands,
|
operands,
|
||||||
|
@ -395,7 +395,7 @@ pub trait Machine<'tcx>: Sized {
|
|||||||
///
|
///
|
||||||
/// This should take care of jumping to the next block (one of `targets`) when asm goto
|
/// This should take care of jumping to the next block (one of `targets`) when asm goto
|
||||||
/// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
|
/// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
|
||||||
/// `InlineAsmOptions::NORETURN` being set.
|
/// naked_asm! or `InlineAsmOptions::NORETURN` being set.
|
||||||
fn eval_inline_asm(
|
fn eval_inline_asm(
|
||||||
_ecx: &mut InterpCx<'tcx, Self>,
|
_ecx: &mut InterpCx<'tcx, Self>,
|
||||||
_template: &'tcx [InlineAsmTemplatePiece],
|
_template: &'tcx [InlineAsmTemplatePiece],
|
||||||
|
@ -3507,11 +3507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
|
fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
|
||||||
let mut diverge = match asm.asm_macro {
|
let mut diverge = asm.asm_macro.diverges(asm.options);
|
||||||
rustc_ast::AsmMacro::Asm => asm.options.contains(ast::InlineAsmOptions::NORETURN),
|
|
||||||
rustc_ast::AsmMacro::GlobalAsm => true,
|
|
||||||
rustc_ast::AsmMacro::NakedAsm => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (op, _op_sp) in asm.operands {
|
for (op, _op_sp) in asm.operands {
|
||||||
match op {
|
match op {
|
||||||
|
@ -2926,16 +2926,16 @@ declare_lint! {
|
|||||||
/// ```rust
|
/// ```rust
|
||||||
/// #![feature(asm_experimental_arch, naked_functions)]
|
/// #![feature(asm_experimental_arch, naked_functions)]
|
||||||
///
|
///
|
||||||
/// use std::arch::asm;
|
/// use std::arch::naked_asm;
|
||||||
///
|
///
|
||||||
/// #[naked]
|
/// #[naked]
|
||||||
/// pub fn default_abi() -> u32 {
|
/// pub fn default_abi() -> u32 {
|
||||||
/// unsafe { asm!("", options(noreturn)); }
|
/// unsafe { naked_asm!(""); }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[naked]
|
/// #[naked]
|
||||||
/// pub extern "Rust" fn rust_abi() -> u32 {
|
/// pub extern "Rust" fn rust_abi() -> u32 {
|
||||||
/// unsafe { asm!("", options(noreturn)); }
|
/// unsafe { naked_asm!(""); }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -4,7 +4,7 @@ use std::fs;
|
|||||||
use std::io::{self, Write as _};
|
use std::io::{self, Write as _};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::InlineAsmTemplatePiece;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range,
|
AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range,
|
||||||
read_target_uint,
|
read_target_uint,
|
||||||
@ -1024,9 +1024,9 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||||||
vec!["real".into(), "unwind".into()]
|
vec!["real".into(), "unwind".into()]
|
||||||
}
|
}
|
||||||
FalseUnwind { unwind: _, .. } => vec!["real".into()],
|
FalseUnwind { unwind: _, .. } => vec!["real".into()],
|
||||||
InlineAsm { options, ref targets, unwind, .. } => {
|
InlineAsm { asm_macro, options, ref targets, unwind, .. } => {
|
||||||
let mut vec = Vec::with_capacity(targets.len() + 1);
|
let mut vec = Vec::with_capacity(targets.len() + 1);
|
||||||
if !options.contains(InlineAsmOptions::NORETURN) {
|
if !asm_macro.diverges(options) {
|
||||||
vec.push("return".into());
|
vec.push("return".into());
|
||||||
}
|
}
|
||||||
vec.resize(targets.len(), "label".into());
|
vec.resize(targets.len(), "label".into());
|
||||||
|
@ -605,6 +605,25 @@ impl CallSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
||||||
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
|
/// The macro that an inline assembly block was created by
|
||||||
|
pub enum InlineAsmMacro {
|
||||||
|
/// The `asm!` macro
|
||||||
|
Asm,
|
||||||
|
/// The `naked_asm!` macro
|
||||||
|
NakedAsm,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlineAsmMacro {
|
||||||
|
pub const fn diverges(self, options: InlineAsmOptions) -> bool {
|
||||||
|
match self {
|
||||||
|
InlineAsmMacro::Asm => options.contains(InlineAsmOptions::NORETURN),
|
||||||
|
InlineAsmMacro::NakedAsm => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Terminators
|
// Terminators
|
||||||
|
|
||||||
@ -859,6 +878,9 @@ pub enum TerminatorKind<'tcx> {
|
|||||||
/// Block ends with an inline assembly block. This is a terminator since
|
/// Block ends with an inline assembly block. This is a terminator since
|
||||||
/// inline assembly is allowed to diverge.
|
/// inline assembly is allowed to diverge.
|
||||||
InlineAsm {
|
InlineAsm {
|
||||||
|
/// Macro used to create this inline asm: one of `asm!` or `naked_asm!`
|
||||||
|
asm_macro: InlineAsmMacro,
|
||||||
|
|
||||||
/// The template for the inline assembly, with placeholders.
|
/// The template for the inline assembly, with placeholders.
|
||||||
template: &'tcx [InlineAsmTemplatePiece],
|
template: &'tcx [InlineAsmTemplatePiece],
|
||||||
|
|
||||||
@ -874,7 +896,7 @@ pub enum TerminatorKind<'tcx> {
|
|||||||
|
|
||||||
/// Valid targets for the inline assembly.
|
/// Valid targets for the inline assembly.
|
||||||
/// The first element is the fallthrough destination, unless
|
/// The first element is the fallthrough destination, unless
|
||||||
/// InlineAsmOptions::NORETURN is set.
|
/// asm_macro == InlineAsmMacro::NakedAsm or InlineAsmOptions::NORETURN is set.
|
||||||
targets: Box<[BasicBlock]>,
|
targets: Box<[BasicBlock]>,
|
||||||
|
|
||||||
/// Action to be taken if the inline assembly unwinds. This is present
|
/// Action to be taken if the inline assembly unwinds. This is present
|
||||||
|
@ -666,6 +666,7 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||||||
},
|
},
|
||||||
|
|
||||||
InlineAsm {
|
InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template: _,
|
template: _,
|
||||||
ref operands,
|
ref operands,
|
||||||
options: _,
|
options: _,
|
||||||
|
@ -576,6 +576,7 @@ macro_rules! make_mir_visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminatorKind::InlineAsm {
|
TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template: _,
|
template: _,
|
||||||
operands,
|
operands,
|
||||||
options: _,
|
options: _,
|
||||||
|
@ -12,7 +12,7 @@ use std::cmp::Ordering;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
|
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
|
||||||
@ -173,6 +173,7 @@ pub struct ClosureExpr<'tcx> {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, HashStable)]
|
#[derive(Clone, Debug, HashStable)]
|
||||||
pub struct InlineAsmExpr<'tcx> {
|
pub struct InlineAsmExpr<'tcx> {
|
||||||
|
pub asm_macro: AsmMacro,
|
||||||
pub template: &'tcx [InlineAsmTemplatePiece],
|
pub template: &'tcx [InlineAsmTemplatePiece],
|
||||||
pub operands: Box<[InlineAsmOperand<'tcx>]>,
|
pub operands: Box<[InlineAsmOperand<'tcx>]>,
|
||||||
pub options: InlineAsmOptions,
|
pub options: InlineAsmOptions,
|
||||||
|
@ -148,7 +148,13 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
|||||||
NamedConst { def_id: _, args: _, user_ty: _ } => {}
|
NamedConst { def_id: _, args: _, user_ty: _ } => {}
|
||||||
ConstParam { param: _, def_id: _ } => {}
|
ConstParam { param: _, def_id: _ } => {}
|
||||||
StaticRef { alloc_id: _, ty: _, def_id: _ } => {}
|
StaticRef { alloc_id: _, ty: _, def_id: _ } => {}
|
||||||
InlineAsm(box InlineAsmExpr { ref operands, template: _, options: _, line_spans: _ }) => {
|
InlineAsm(box InlineAsmExpr {
|
||||||
|
asm_macro: _,
|
||||||
|
ref operands,
|
||||||
|
template: _,
|
||||||
|
options: _,
|
||||||
|
line_spans: _,
|
||||||
|
}) => {
|
||||||
for op in &**operands {
|
for op in &**operands {
|
||||||
use InlineAsmOperand::*;
|
use InlineAsmOperand::*;
|
||||||
match op {
|
match op {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use rustc_ast::InlineAsmOptions;
|
use rustc_ast::{AsmMacro, InlineAsmOptions};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
@ -384,6 +384,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
ExprKind::InlineAsm(box InlineAsmExpr {
|
ExprKind::InlineAsm(box InlineAsmExpr {
|
||||||
|
asm_macro,
|
||||||
template,
|
template,
|
||||||
ref operands,
|
ref operands,
|
||||||
options,
|
options,
|
||||||
@ -392,11 +393,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
use rustc_middle::{mir, thir};
|
use rustc_middle::{mir, thir};
|
||||||
|
|
||||||
let destination_block = this.cfg.start_new_block();
|
let destination_block = this.cfg.start_new_block();
|
||||||
let mut targets = if options.contains(InlineAsmOptions::NORETURN) {
|
let mut targets =
|
||||||
vec![]
|
if asm_macro.diverges(options) { vec![] } else { vec![destination_block] };
|
||||||
} else {
|
|
||||||
vec![destination_block]
|
|
||||||
};
|
|
||||||
|
|
||||||
let operands = operands
|
let operands = operands
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -474,7 +472,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
|
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let asm_macro = match asm_macro {
|
||||||
|
AsmMacro::Asm => InlineAsmMacro::Asm,
|
||||||
|
AsmMacro::GlobalAsm => {
|
||||||
|
span_bug!(expr_span, "unexpected global_asm! in inline asm")
|
||||||
|
}
|
||||||
|
AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm,
|
||||||
|
};
|
||||||
|
|
||||||
this.cfg.terminate(block, source_info, TerminatorKind::InlineAsm {
|
this.cfg.terminate(block, source_info, TerminatorKind::InlineAsm {
|
||||||
|
asm_macro,
|
||||||
template,
|
template,
|
||||||
operands,
|
operands,
|
||||||
options,
|
options,
|
||||||
|
@ -672,6 +672,7 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr {
|
hir::ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(Box::new(InlineAsmExpr {
|
||||||
|
asm_macro: asm.asm_macro,
|
||||||
template: asm.template,
|
template: asm.template,
|
||||||
operands: asm
|
operands: asm
|
||||||
.operands
|
.operands
|
||||||
|
@ -818,10 +818,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) {
|
fn print_inline_asm_expr(&mut self, expr: &InlineAsmExpr<'tcx>, depth_lvl: usize) {
|
||||||
let InlineAsmExpr { template, operands, options, line_spans } = expr;
|
let InlineAsmExpr { asm_macro, template, operands, options, line_spans } = expr;
|
||||||
|
|
||||||
print_indented!(self, "InlineAsmExpr {", depth_lvl);
|
print_indented!(self, "InlineAsmExpr {", depth_lvl);
|
||||||
|
|
||||||
|
print_indented!(self, format!("asm_macro: {:?}", asm_macro), depth_lvl + 1);
|
||||||
|
|
||||||
print_indented!(self, "template: [", depth_lvl + 1);
|
print_indented!(self, "template: [", depth_lvl + 1);
|
||||||
for template_piece in template.iter() {
|
for template_piece in template.iter() {
|
||||||
print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2);
|
print_indented!(self, format!("{:?}", template_piece), depth_lvl + 2);
|
||||||
|
@ -481,6 +481,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TerminatorKind::InlineAsm {
|
TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template: _,
|
template: _,
|
||||||
ref operands,
|
ref operands,
|
||||||
options: _,
|
options: _,
|
||||||
|
@ -499,7 +499,7 @@ passes_naked_functions_incompatible_attribute =
|
|||||||
|
|
||||||
passes_naked_functions_must_naked_asm =
|
passes_naked_functions_must_naked_asm =
|
||||||
the `asm!` macro is not allowed in naked functions
|
the `asm!` macro is not allowed in naked functions
|
||||||
.suggestion = consider using the `naked_asm!` macro instead
|
.label = consider using the `naked_asm!` macro instead
|
||||||
|
|
||||||
passes_no_link =
|
passes_no_link =
|
||||||
attribute should be applied to an `extern crate` item
|
attribute should be applied to an `extern crate` item
|
||||||
|
@ -1190,9 +1190,8 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for NakedFunctionsAsmBlock {
|
|||||||
#[diag(passes_naked_functions_must_naked_asm, code = E0787)]
|
#[diag(passes_naked_functions_must_naked_asm, code = E0787)]
|
||||||
pub(crate) struct NakedFunctionsMustNakedAsm {
|
pub(crate) struct NakedFunctionsMustNakedAsm {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[suggestion(code = "naked_asm!", applicability = "machine-applicable")]
|
|
||||||
pub macro_span: Span,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
@ -7,10 +7,11 @@ use rustc_hir::intravisit::Visitor;
|
|||||||
use rustc_hir::{ExprKind, HirIdSet, StmtKind};
|
use rustc_hir::{ExprKind, HirIdSet, StmtKind};
|
||||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
|
use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
|
||||||
|
use rustc_span::Span;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::{BytePos, Span};
|
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
@ -137,10 +138,7 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
|
|||||||
ItemKind::InlineAsm => {
|
ItemKind::InlineAsm => {
|
||||||
has_err = true;
|
has_err = true;
|
||||||
|
|
||||||
// the span that contains the `asm!` call,
|
tcx.dcx().emit_err(NakedFunctionsMustNakedAsm { span });
|
||||||
// so tooling can replace it with `naked_asm!`
|
|
||||||
let macro_span = span.with_hi(span.lo() + BytePos("asm!".len() as u32));
|
|
||||||
tcx.dcx().emit_err(NakedFunctionsMustNakedAsm { span, macro_span });
|
|
||||||
}
|
}
|
||||||
ItemKind::NonAsm => {
|
ItemKind::NonAsm => {
|
||||||
must_show_error = true;
|
must_show_error = true;
|
||||||
@ -210,8 +208,7 @@ impl CheckInlineAssembly {
|
|||||||
self.items.push((ItemKind::NonAsm, span));
|
self.items.push((ItemKind::NonAsm, span));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::InlineAsm(asm) => {
|
ExprKind::InlineAsm(asm) => match asm.asm_macro {
|
||||||
match asm.asm_macro {
|
|
||||||
rustc_ast::AsmMacro::Asm => {
|
rustc_ast::AsmMacro::Asm => {
|
||||||
self.items.push((ItemKind::InlineAsm, span));
|
self.items.push((ItemKind::InlineAsm, span));
|
||||||
}
|
}
|
||||||
@ -219,10 +216,9 @@ impl CheckInlineAssembly {
|
|||||||
self.items.push((ItemKind::NakedAsm, span));
|
self.items.push((ItemKind::NakedAsm, span));
|
||||||
}
|
}
|
||||||
rustc_ast::AsmMacro::GlobalAsm => {
|
rustc_ast::AsmMacro::GlobalAsm => {
|
||||||
// not allowed in this position
|
span_bug!(span, "`global_asm!` is not allowed in this position")
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
ExprKind::DropTemps(..) | ExprKind::Block(..) => {
|
ExprKind::DropTemps(..) | ExprKind::Block(..) => {
|
||||||
hir::intravisit::walk_expr(self, expr);
|
hir::intravisit::walk_expr(self, expr);
|
||||||
|
@ -655,6 +655,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::TerminatorKind::InlineAsm {
|
mir::TerminatorKind::InlineAsm {
|
||||||
|
asm_macro: _,
|
||||||
template,
|
template,
|
||||||
operands,
|
operands,
|
||||||
options,
|
options,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs};
|
use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args};
|
||||||
|
|
||||||
use crate::rewrite::RewriteContext;
|
use crate::rewrite::RewriteContext;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
|
pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::arch::asm!("ud2", options(noreturn));
|
core::arch::naked_asm!("ud2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ extern "C" fn vanilla_weak_linkage() -> u32 {
|
|||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
#[linkage = "weak"]
|
#[linkage = "weak"]
|
||||||
extern "C" fn naked_weak_linkage() -> u32 {
|
extern "C" fn naked_weak_linkage() -> u32 {
|
||||||
unsafe { naked_asm!("mov rax, 42", "ret", options(noreturn)) }
|
unsafe { naked_asm!("mov rax, 42", "ret") }
|
||||||
}
|
}
|
||||||
|
|
||||||
// functions that are declared in an `extern "C"` block are currently not exported
|
// functions that are declared in an `extern "C"` block are currently not exported
|
||||||
|
@ -74,9 +74,7 @@ error[E0787]: the `asm!` macro is not allowed in naked functions
|
|||||||
--> $DIR/naked-functions.rs:13:5
|
--> $DIR/naked-functions.rs:13:5
|
||||||
|
|
|
|
||||||
LL | asm!("", options(raw));
|
LL | asm!("", options(raw));
|
||||||
| ----^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^ consider using the `naked_asm!` macro instead
|
||||||
| |
|
|
||||||
| help: consider using the `naked_asm!` macro instead: `naked_asm!`
|
|
||||||
|
|
||||||
error: patterns not allowed in naked function parameters
|
error: patterns not allowed in naked function parameters
|
||||||
--> $DIR/naked-functions.rs:25:5
|
--> $DIR/naked-functions.rs:25:5
|
||||||
|
Loading…
Reference in New Issue
Block a user