mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Add asm label support to AST and HIR
This commit is contained in:
parent
8f359beca4
commit
93fa8579c6
@ -2294,6 +2294,9 @@ pub enum InlineAsmOperand {
|
|||||||
Sym {
|
Sym {
|
||||||
sym: InlineAsmSym,
|
sym: InlineAsmSym,
|
||||||
},
|
},
|
||||||
|
Label {
|
||||||
|
block: P<Block>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineAsmOperand {
|
impl InlineAsmOperand {
|
||||||
@ -2303,7 +2306,7 @@ impl InlineAsmOperand {
|
|||||||
| Self::Out { reg, .. }
|
| Self::Out { reg, .. }
|
||||||
| Self::InOut { reg, .. }
|
| Self::InOut { reg, .. }
|
||||||
| Self::SplitInOut { reg, .. } => Some(reg),
|
| Self::SplitInOut { reg, .. } => Some(reg),
|
||||||
Self::Const { .. } | Self::Sym { .. } => None,
|
Self::Const { .. } | Self::Sym { .. } | Self::Label { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1330,6 +1330,7 @@ pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
|
|||||||
}
|
}
|
||||||
InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
|
InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
|
||||||
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
|
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
|
||||||
|
InlineAsmOperand::Label { block } => vis.visit_block(block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -885,6 +885,7 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm)
|
|||||||
try_visit!(visitor.visit_anon_const(anon_const))
|
try_visit!(visitor.visit_anon_const(anon_const))
|
||||||
}
|
}
|
||||||
InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
|
InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)),
|
||||||
|
InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
|
@ -88,6 +88,9 @@ ast_lowering_invalid_abi_suggestion = did you mean
|
|||||||
ast_lowering_invalid_asm_template_modifier_const =
|
ast_lowering_invalid_asm_template_modifier_const =
|
||||||
asm template modifiers are not allowed for `const` arguments
|
asm template modifiers are not allowed for `const` arguments
|
||||||
|
|
||||||
|
ast_lowering_invalid_asm_template_modifier_label =
|
||||||
|
asm template modifiers are not allowed for `label` arguments
|
||||||
|
|
||||||
ast_lowering_invalid_asm_template_modifier_reg_class =
|
ast_lowering_invalid_asm_template_modifier_reg_class =
|
||||||
invalid asm template modifier for this register class
|
invalid asm template modifier for this register class
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringE
|
|||||||
use super::errors::{
|
use super::errors::{
|
||||||
AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
|
AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
|
||||||
InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
|
InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
|
||||||
InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierRegClassSub,
|
InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
|
||||||
InvalidAsmTemplateModifierSym, InvalidRegister, InvalidRegisterClass, RegisterClassOnlyClobber,
|
InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
|
||||||
RegisterConflict,
|
InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict,
|
||||||
};
|
};
|
||||||
use super::LoweringContext;
|
use super::LoweringContext;
|
||||||
|
|
||||||
@ -236,6 +236,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InlineAsmOperand::Label { block } => {
|
||||||
|
if !self.tcx.features().asm_goto {
|
||||||
|
feature_err(
|
||||||
|
sess,
|
||||||
|
sym::asm_goto,
|
||||||
|
*op_sp,
|
||||||
|
"label operands for inline assembly are unstable",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
hir::InlineAsmOperand::Label { block: self.lower_block(block, false) }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
(op, self.lower_span(*op_sp))
|
(op, self.lower_span(*op_sp))
|
||||||
})
|
})
|
||||||
@ -295,6 +307,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
op_span: op_sp,
|
op_span: op_sp,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
hir::InlineAsmOperand::Label { .. } => {
|
||||||
|
self.dcx().emit_err(InvalidAsmTemplateModifierLabel {
|
||||||
|
placeholder_span,
|
||||||
|
op_span: op_sp,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,7 +352,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
hir::InlineAsmOperand::Const { .. }
|
hir::InlineAsmOperand::Const { .. }
|
||||||
| hir::InlineAsmOperand::SymFn { .. }
|
| hir::InlineAsmOperand::SymFn { .. }
|
||||||
| hir::InlineAsmOperand::SymStatic { .. } => {
|
| hir::InlineAsmOperand::SymStatic { .. }
|
||||||
|
| hir::InlineAsmOperand::Label { .. } => {
|
||||||
unreachable!("{op:?} is not a register operand");
|
unreachable!("{op:?} is not a register operand");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -262,6 +262,16 @@ pub struct InvalidAsmTemplateModifierSym {
|
|||||||
pub op_span: Span,
|
pub op_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
|
#[diag(ast_lowering_invalid_asm_template_modifier_label)]
|
||||||
|
pub struct InvalidAsmTemplateModifierLabel {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(ast_lowering_template_modifier)]
|
||||||
|
pub placeholder_span: Span,
|
||||||
|
#[label(ast_lowering_argument)]
|
||||||
|
pub op_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic, Clone, Copy)]
|
#[derive(Diagnostic, Clone, Copy)]
|
||||||
#[diag(ast_lowering_register_class_only_clobber)]
|
#[diag(ast_lowering_register_class_only_clobber)]
|
||||||
pub struct RegisterClassOnlyClobber {
|
pub struct RegisterClassOnlyClobber {
|
||||||
|
@ -1331,6 +1331,10 @@ impl<'a> State<'a> {
|
|||||||
s.print_path(&sym.path, true, 0);
|
s.print_path(&sym.path, true, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InlineAsmOperand::Label { block } => {
|
||||||
|
s.head("label");
|
||||||
|
s.print_block(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AsmArg::ClobberAbi(abi) => {
|
AsmArg::ClobberAbi(abi) => {
|
||||||
|
@ -166,6 +166,9 @@ pub fn parse_asm_args<'a>(
|
|||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
};
|
};
|
||||||
ast::InlineAsmOperand::Sym { sym }
|
ast::InlineAsmOperand::Sym { sym }
|
||||||
|
} else if !is_global_asm && p.eat_keyword(sym::label) {
|
||||||
|
let block = p.parse_block()?;
|
||||||
|
ast::InlineAsmOperand::Label { block }
|
||||||
} else if allow_templates {
|
} else if allow_templates {
|
||||||
let template = p.parse_expr()?;
|
let template = p.parse_expr()?;
|
||||||
// If it can't possibly expand to a string, provide diagnostics here to include other
|
// If it can't possibly expand to a string, provide diagnostics here to include other
|
||||||
|
@ -76,7 +76,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||||||
hir::InlineAsmOperand::In { .. }
|
hir::InlineAsmOperand::In { .. }
|
||||||
| hir::InlineAsmOperand::Out { .. }
|
| hir::InlineAsmOperand::Out { .. }
|
||||||
| hir::InlineAsmOperand::InOut { .. }
|
| hir::InlineAsmOperand::InOut { .. }
|
||||||
| hir::InlineAsmOperand::SplitInOut { .. } => {
|
| hir::InlineAsmOperand::SplitInOut { .. }
|
||||||
|
| hir::InlineAsmOperand::Label { .. } => {
|
||||||
span_bug!(*op_sp, "invalid operand type for global_asm!")
|
span_bug!(*op_sp, "invalid operand type for global_asm!")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -345,6 +345,8 @@ declare_features! (
|
|||||||
(unstable, asm_const, "1.58.0", Some(93332)),
|
(unstable, asm_const, "1.58.0", Some(93332)),
|
||||||
/// Enables experimental inline assembly support for additional architectures.
|
/// Enables experimental inline assembly support for additional architectures.
|
||||||
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
|
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
|
||||||
|
/// Allows using `label` operands in inline assembly.
|
||||||
|
(unstable, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)),
|
||||||
/// Allows the `may_unwind` option in inline assembly.
|
/// Allows the `may_unwind` option in inline assembly.
|
||||||
(unstable, asm_unwind, "1.58.0", Some(93334)),
|
(unstable, asm_unwind, "1.58.0", Some(93334)),
|
||||||
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
|
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
|
||||||
|
@ -2645,6 +2645,9 @@ pub enum InlineAsmOperand<'hir> {
|
|||||||
path: QPath<'hir>,
|
path: QPath<'hir>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
},
|
},
|
||||||
|
Label {
|
||||||
|
block: &'hir Block<'hir>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> InlineAsmOperand<'hir> {
|
impl<'hir> InlineAsmOperand<'hir> {
|
||||||
@ -2654,7 +2657,10 @@ impl<'hir> InlineAsmOperand<'hir> {
|
|||||||
| Self::Out { reg, .. }
|
| Self::Out { reg, .. }
|
||||||
| Self::InOut { reg, .. }
|
| Self::InOut { reg, .. }
|
||||||
| Self::SplitInOut { reg, .. } => Some(reg),
|
| Self::SplitInOut { reg, .. } => Some(reg),
|
||||||
Self::Const { .. } | Self::SymFn { .. } | Self::SymStatic { .. } => None,
|
Self::Const { .. }
|
||||||
|
| Self::SymFn { .. }
|
||||||
|
| Self::SymStatic { .. }
|
||||||
|
| Self::Label { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2675,6 +2681,12 @@ pub struct InlineAsm<'hir> {
|
|||||||
pub line_spans: &'hir [Span],
|
pub line_spans: &'hir [Span],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl InlineAsm<'_> {
|
||||||
|
pub fn contains_label(&self) -> bool {
|
||||||
|
self.operands.iter().any(|x| matches!(x.0, InlineAsmOperand::Label { .. }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents a parameter in a function header.
|
/// Represents a parameter in a function header.
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub struct Param<'hir> {
|
pub struct Param<'hir> {
|
||||||
|
@ -1290,6 +1290,7 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(
|
|||||||
InlineAsmOperand::SymStatic { path, .. } => {
|
InlineAsmOperand::SymStatic { path, .. } => {
|
||||||
try_visit!(visitor.visit_qpath(path, id, *op_sp));
|
try_visit!(visitor.visit_qpath(path, id, *op_sp));
|
||||||
}
|
}
|
||||||
|
InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
V::Result::output()
|
V::Result::output()
|
||||||
|
@ -470,6 +470,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
// No special checking is needed for labels.
|
||||||
|
hir::InlineAsmOperand::Label { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1265,6 +1265,10 @@ impl<'a> State<'a> {
|
|||||||
s.space();
|
s.space();
|
||||||
s.print_qpath(path, true);
|
s.print_qpath(path, true);
|
||||||
}
|
}
|
||||||
|
hir::InlineAsmOperand::Label { block } => {
|
||||||
|
s.head("label");
|
||||||
|
s.print_block(block);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
AsmArg::Options(opts) => {
|
AsmArg::Options(opts) => {
|
||||||
s.word("options");
|
s.word("options");
|
||||||
|
@ -3264,6 +3264,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// be well-formed.
|
// be well-formed.
|
||||||
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
|
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
|
||||||
hir::InlineAsmOperand::SymStatic { .. } => {}
|
hir::InlineAsmOperand::SymStatic { .. } => {}
|
||||||
|
hir::InlineAsmOperand::Label { block } => {
|
||||||
|
self.check_block_no_value(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
|
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {
|
||||||
|
@ -293,6 +293,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
|
|||||||
| hir::InlineAsmOperand::Const { .. }
|
| hir::InlineAsmOperand::Const { .. }
|
||||||
| hir::InlineAsmOperand::SymFn { .. }
|
| hir::InlineAsmOperand::SymFn { .. }
|
||||||
| hir::InlineAsmOperand::SymStatic { .. } => {}
|
| hir::InlineAsmOperand::SymStatic { .. } => {}
|
||||||
|
hir::InlineAsmOperand::Label { block } => {
|
||||||
|
self.walk_block(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,6 +656,9 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
|
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
|
||||||
InlineAsmOperand::SymStatic { def_id }
|
InlineAsmOperand::SymStatic { def_id }
|
||||||
}
|
}
|
||||||
|
hir::InlineAsmOperand::Label { .. } => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
options: asm.options,
|
options: asm.options,
|
||||||
|
@ -446,7 +446,8 @@ fn collect_items_rec<'tcx>(
|
|||||||
hir::InlineAsmOperand::In { .. }
|
hir::InlineAsmOperand::In { .. }
|
||||||
| hir::InlineAsmOperand::Out { .. }
|
| hir::InlineAsmOperand::Out { .. }
|
||||||
| hir::InlineAsmOperand::InOut { .. }
|
| hir::InlineAsmOperand::InOut { .. }
|
||||||
| hir::InlineAsmOperand::SplitInOut { .. } => {
|
| hir::InlineAsmOperand::SplitInOut { .. }
|
||||||
|
| hir::InlineAsmOperand::Label { .. } => {
|
||||||
span_bug!(*op_sp, "invalid operand type for global_asm!")
|
span_bug!(*op_sp, "invalid operand type for global_asm!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a block. No inner attributes are allowed.
|
/// Parses a block. No inner attributes are allowed.
|
||||||
pub(super) fn parse_block(&mut self) -> PResult<'a, P<Block>> {
|
pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
|
||||||
let (attrs, block) = self.parse_inner_attrs_and_block()?;
|
let (attrs, block) = self.parse_inner_attrs_and_block()?;
|
||||||
if let [.., last] = &*attrs {
|
if let [.., last] = &*attrs {
|
||||||
self.error_on_forbidden_inner_attr(
|
self.error_on_forbidden_inner_attr(
|
||||||
|
@ -86,7 +86,6 @@ use crate::errors;
|
|||||||
use self::LiveNodeKind::*;
|
use self::LiveNodeKind::*;
|
||||||
use self::VarKind::*;
|
use self::VarKind::*;
|
||||||
|
|
||||||
use rustc_ast::InlineAsmOptions;
|
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::*;
|
use rustc_hir::def::*;
|
||||||
@ -416,6 +415,12 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
|
|||||||
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
|
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inline assembly may contain labels.
|
||||||
|
hir::ExprKind::InlineAsm(asm) if asm.contains_label() => {
|
||||||
|
self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
|
||||||
|
intravisit::walk_expr(self, expr);
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise, live nodes are not required:
|
// otherwise, live nodes are not required:
|
||||||
hir::ExprKind::Index(..)
|
hir::ExprKind::Index(..)
|
||||||
| hir::ExprKind::Field(..)
|
| hir::ExprKind::Field(..)
|
||||||
@ -1045,20 +1050,53 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
| hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
|
| hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(e, succ),
|
||||||
|
|
||||||
hir::ExprKind::InlineAsm(asm) => {
|
hir::ExprKind::InlineAsm(asm) => {
|
||||||
// Handle non-returning asm
|
//
|
||||||
let mut succ = if asm.options.contains(InlineAsmOptions::NORETURN) {
|
// (inputs)
|
||||||
self.exit_ln
|
// |
|
||||||
} else {
|
// v
|
||||||
succ
|
// (outputs)
|
||||||
};
|
// / \
|
||||||
|
// | |
|
||||||
|
// v v
|
||||||
|
// (labels)(fallthrough)
|
||||||
|
// | |
|
||||||
|
// v v
|
||||||
|
// ( succ / exit_ln )
|
||||||
|
|
||||||
// Do a first pass for writing outputs only
|
// Handle non-returning asm
|
||||||
|
let mut succ =
|
||||||
|
if self.typeck_results.expr_ty(expr).is_never() { self.exit_ln } else { succ };
|
||||||
|
|
||||||
|
// Do a first pass for labels only
|
||||||
|
if asm.contains_label() {
|
||||||
|
let ln = self.live_node(expr.hir_id, expr.span);
|
||||||
|
self.init_from_succ(ln, succ);
|
||||||
|
for (op, _op_sp) in asm.operands.iter().rev() {
|
||||||
|
match op {
|
||||||
|
hir::InlineAsmOperand::Label { block } => {
|
||||||
|
let label_ln = self.propagate_through_block(block, succ);
|
||||||
|
self.merge_from_succ(ln, label_ln);
|
||||||
|
}
|
||||||
|
hir::InlineAsmOperand::In { .. }
|
||||||
|
| hir::InlineAsmOperand::Out { .. }
|
||||||
|
| hir::InlineAsmOperand::InOut { .. }
|
||||||
|
| hir::InlineAsmOperand::SplitInOut { .. }
|
||||||
|
| hir::InlineAsmOperand::Const { .. }
|
||||||
|
| hir::InlineAsmOperand::SymFn { .. }
|
||||||
|
| hir::InlineAsmOperand::SymStatic { .. } => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
succ = ln;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a second pass for writing outputs only
|
||||||
for (op, _op_sp) in asm.operands.iter().rev() {
|
for (op, _op_sp) in asm.operands.iter().rev() {
|
||||||
match op {
|
match op {
|
||||||
hir::InlineAsmOperand::In { .. }
|
hir::InlineAsmOperand::In { .. }
|
||||||
| hir::InlineAsmOperand::Const { .. }
|
| hir::InlineAsmOperand::Const { .. }
|
||||||
| hir::InlineAsmOperand::SymFn { .. }
|
| hir::InlineAsmOperand::SymFn { .. }
|
||||||
| hir::InlineAsmOperand::SymStatic { .. } => {}
|
| hir::InlineAsmOperand::SymStatic { .. }
|
||||||
|
| hir::InlineAsmOperand::Label { .. } => {}
|
||||||
hir::InlineAsmOperand::Out { expr, .. } => {
|
hir::InlineAsmOperand::Out { expr, .. } => {
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
succ = self.write_place(expr, succ, ACC_WRITE);
|
succ = self.write_place(expr, succ, ACC_WRITE);
|
||||||
@ -1075,7 +1113,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then do a second pass for inputs
|
// Then do a third pass for inputs
|
||||||
for (op, _op_sp) in asm.operands.iter().rev() {
|
for (op, _op_sp) in asm.operands.iter().rev() {
|
||||||
match op {
|
match op {
|
||||||
hir::InlineAsmOperand::In { expr, .. } => {
|
hir::InlineAsmOperand::In { expr, .. } => {
|
||||||
@ -1097,7 +1135,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
hir::InlineAsmOperand::Const { .. }
|
hir::InlineAsmOperand::Const { .. }
|
||||||
| hir::InlineAsmOperand::SymFn { .. }
|
| hir::InlineAsmOperand::SymFn { .. }
|
||||||
| hir::InlineAsmOperand::SymStatic { .. } => {}
|
| hir::InlineAsmOperand::SymStatic { .. }
|
||||||
|
| hir::InlineAsmOperand::Label { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
succ
|
succ
|
||||||
|
@ -237,7 +237,8 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
|||||||
InlineAsmOperand::In { .. }
|
InlineAsmOperand::In { .. }
|
||||||
| InlineAsmOperand::Out { .. }
|
| InlineAsmOperand::Out { .. }
|
||||||
| InlineAsmOperand::InOut { .. }
|
| InlineAsmOperand::InOut { .. }
|
||||||
| InlineAsmOperand::SplitInOut { .. } => Some(op_sp),
|
| InlineAsmOperand::SplitInOut { .. }
|
||||||
|
| InlineAsmOperand::Label { .. } => Some(op_sp),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if !unsupported_operands.is_empty() {
|
if !unsupported_operands.is_empty() {
|
||||||
|
@ -1246,6 +1246,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||||||
self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
|
self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
|
||||||
}
|
}
|
||||||
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
|
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
|
||||||
|
InlineAsmOperand::Label { block } => self.visit_block(block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,6 +399,7 @@ symbols! {
|
|||||||
asm,
|
asm,
|
||||||
asm_const,
|
asm_const,
|
||||||
asm_experimental_arch,
|
asm_experimental_arch,
|
||||||
|
asm_goto,
|
||||||
asm_sym,
|
asm_sym,
|
||||||
asm_unwind,
|
asm_unwind,
|
||||||
assert,
|
assert,
|
||||||
|
@ -255,6 +255,9 @@ fn never_loop_expr<'tcx>(
|
|||||||
InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => {
|
InlineAsmOperand::Const { .. } | InlineAsmOperand::SymFn { .. } | InlineAsmOperand::SymStatic { .. } => {
|
||||||
NeverLoopResult::Normal
|
NeverLoopResult::Normal
|
||||||
},
|
},
|
||||||
|
InlineAsmOperand::Label { block } => {
|
||||||
|
never_loop_block(cx, block, local_labels, main_loop_id)
|
||||||
|
}
|
||||||
})),
|
})),
|
||||||
ExprKind::OffsetOf(_, _)
|
ExprKind::OffsetOf(_, _)
|
||||||
| ExprKind::Yield(_, _)
|
| ExprKind::Yield(_, _)
|
||||||
|
@ -835,6 +835,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||||||
self.hash_body(anon_const.body);
|
self.hash_body(anon_const.body);
|
||||||
},
|
},
|
||||||
InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
|
InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
|
||||||
|
InlineAsmOperand::Label { block } => self.hash_block(block),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user