mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Fix name fetching being incorrect for asm operands
This commit is contained in:
parent
564926ac99
commit
c075a9980e
@ -105,7 +105,7 @@ pub struct BodySourceMap {
|
|||||||
// format_args!
|
// format_args!
|
||||||
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
||||||
// asm!
|
// asm!
|
||||||
FxHashMap<ExprId, Vec<(syntax::TextRange, usize, Option<Name>)>>,
|
FxHashMap<ExprId, Vec<(syntax::TextRange, usize)>>,
|
||||||
)>,
|
)>,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ impl BodySourceMap {
|
|||||||
pub fn asm_template_args(
|
pub fn asm_template_args(
|
||||||
&self,
|
&self,
|
||||||
node: InFile<&ast::AsmExpr>,
|
node: InFile<&ast::AsmExpr>,
|
||||||
) -> Option<(ExprId, &[(syntax::TextRange, usize, Option<Name>)])> {
|
) -> Option<(ExprId, &[(syntax::TextRange, usize)])> {
|
||||||
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
||||||
let expr = self.expr_map.get(&src)?;
|
let expr = self.expr_map.get(&src)?;
|
||||||
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
|
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
|
||||||
@ -487,7 +487,7 @@ impl BodySourceMap {
|
|||||||
&self,
|
&self,
|
||||||
) -> Option<&(
|
) -> Option<&(
|
||||||
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
|
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
|
||||||
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, usize, Option<Name>)>>,
|
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, usize)>>,
|
||||||
)> {
|
)> {
|
||||||
self.template_map.as_deref()
|
self.template_map.as_deref()
|
||||||
}
|
}
|
||||||
|
@ -65,80 +65,89 @@ impl ExprCollector<'_> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast::AsmPiece::AsmOperandNamed(op) => {
|
ast::AsmPiece::AsmOperandNamed(op) => {
|
||||||
if let Some(name) = op.name() {
|
let name = op.name().map(|name| Symbol::intern(&name.text()));
|
||||||
let sym = Symbol::intern(&name.text());
|
if let Some(name) = &name {
|
||||||
named_args.insert(sym.clone(), slot);
|
named_args.insert(name.clone(), slot);
|
||||||
named_pos.insert(slot, sym);
|
named_pos.insert(slot, name.clone());
|
||||||
}
|
}
|
||||||
let Some(op) = op.asm_operand() else { continue };
|
let Some(op) = op.asm_operand() else { continue };
|
||||||
match op {
|
(
|
||||||
ast::AsmOperand::AsmRegOperand(op) => {
|
name.map(Name::new_symbol_root),
|
||||||
let Some(dir_spec) = op.asm_dir_spec() else {
|
match op {
|
||||||
continue;
|
ast::AsmOperand::AsmRegOperand(op) => {
|
||||||
};
|
let Some(dir_spec) = op.asm_dir_spec() else {
|
||||||
let Some(reg) = lower_reg(op.asm_reg_spec()) else {
|
continue;
|
||||||
continue;
|
};
|
||||||
};
|
let Some(reg) = lower_reg(op.asm_reg_spec()) else {
|
||||||
if dir_spec.in_token().is_some() {
|
continue;
|
||||||
let expr = self.collect_expr_opt(
|
};
|
||||||
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
if dir_spec.in_token().is_some() {
|
||||||
);
|
let expr = self.collect_expr_opt(
|
||||||
AsmOperand::In { reg, expr }
|
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
||||||
} else if dir_spec.out_token().is_some() {
|
);
|
||||||
let expr = self.collect_expr_opt(
|
AsmOperand::In { reg, expr }
|
||||||
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
} else if dir_spec.out_token().is_some() {
|
||||||
);
|
let expr = self.collect_expr_opt(
|
||||||
AsmOperand::Out { reg, expr: Some(expr), late: false }
|
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
||||||
} else if dir_spec.lateout_token().is_some() {
|
);
|
||||||
let expr = self.collect_expr_opt(
|
AsmOperand::Out { reg, expr: Some(expr), late: false }
|
||||||
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
} else if dir_spec.lateout_token().is_some() {
|
||||||
);
|
let expr = self.collect_expr_opt(
|
||||||
AsmOperand::Out { reg, expr: Some(expr), late: true }
|
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
||||||
} else if dir_spec.inout_token().is_some() {
|
);
|
||||||
let Some(op_expr) = op.asm_operand_expr() else { continue };
|
AsmOperand::Out { reg, expr: Some(expr), late: true }
|
||||||
let in_expr = self.collect_expr_opt(op_expr.in_expr());
|
} else if dir_spec.inout_token().is_some() {
|
||||||
let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it));
|
let Some(op_expr) = op.asm_operand_expr() else { continue };
|
||||||
match out_expr {
|
let in_expr = self.collect_expr_opt(op_expr.in_expr());
|
||||||
Some(out_expr) => AsmOperand::SplitInOut {
|
let out_expr =
|
||||||
reg,
|
op_expr.out_expr().map(|it| self.collect_expr(it));
|
||||||
in_expr,
|
match out_expr {
|
||||||
out_expr: Some(out_expr),
|
Some(out_expr) => AsmOperand::SplitInOut {
|
||||||
late: false,
|
reg,
|
||||||
},
|
in_expr,
|
||||||
None => AsmOperand::InOut { reg, expr: in_expr, late: false },
|
out_expr: Some(out_expr),
|
||||||
|
late: false,
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
AsmOperand::InOut { reg, expr: in_expr, late: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if dir_spec.inlateout_token().is_some() {
|
||||||
|
let Some(op_expr) = op.asm_operand_expr() else { continue };
|
||||||
|
let in_expr = self.collect_expr_opt(op_expr.in_expr());
|
||||||
|
let out_expr =
|
||||||
|
op_expr.out_expr().map(|it| self.collect_expr(it));
|
||||||
|
match out_expr {
|
||||||
|
Some(out_expr) => AsmOperand::SplitInOut {
|
||||||
|
reg,
|
||||||
|
in_expr,
|
||||||
|
out_expr: Some(out_expr),
|
||||||
|
late: false,
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
AsmOperand::InOut { reg, expr: in_expr, late: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
} else if dir_spec.inlateout_token().is_some() {
|
|
||||||
let Some(op_expr) = op.asm_operand_expr() else { continue };
|
|
||||||
let in_expr = self.collect_expr_opt(op_expr.in_expr());
|
|
||||||
let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it));
|
|
||||||
match out_expr {
|
|
||||||
Some(out_expr) => AsmOperand::SplitInOut {
|
|
||||||
reg,
|
|
||||||
in_expr,
|
|
||||||
out_expr: Some(out_expr),
|
|
||||||
late: false,
|
|
||||||
},
|
|
||||||
None => AsmOperand::InOut { reg, expr: in_expr, late: false },
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
ast::AsmOperand::AsmLabel(l) => {
|
||||||
ast::AsmOperand::AsmLabel(l) => {
|
AsmOperand::Label(self.collect_block_opt(l.block_expr()))
|
||||||
AsmOperand::Label(self.collect_block_opt(l.block_expr()))
|
}
|
||||||
}
|
ast::AsmOperand::AsmConst(c) => {
|
||||||
ast::AsmOperand::AsmConst(c) => {
|
AsmOperand::Const(self.collect_expr_opt(c.expr()))
|
||||||
AsmOperand::Const(self.collect_expr_opt(c.expr()))
|
}
|
||||||
}
|
ast::AsmOperand::AsmSym(s) => {
|
||||||
ast::AsmOperand::AsmSym(s) => {
|
let Some(path) =
|
||||||
let Some(path) =
|
s.path().and_then(|p| self.expander.parse_path(self.db, p))
|
||||||
s.path().and_then(|p| self.expander.parse_path(self.db, p))
|
else {
|
||||||
else {
|
continue;
|
||||||
continue;
|
};
|
||||||
};
|
AsmOperand::Sym(path)
|
||||||
AsmOperand::Sym(path)
|
}
|
||||||
}
|
},
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
operands.push(op);
|
operands.push(op);
|
||||||
@ -204,7 +213,7 @@ impl ExprCollector<'_> {
|
|||||||
rustc_parse_format::Piece::NextArgument(arg) => {
|
rustc_parse_format::Piece::NextArgument(arg) => {
|
||||||
// let span = arg_spans.next();
|
// let span = arg_spans.next();
|
||||||
|
|
||||||
let (operand_idx, name) = match arg.position {
|
let (operand_idx, _name) = match arg.position {
|
||||||
rustc_parse_format::ArgumentIs(idx)
|
rustc_parse_format::ArgumentIs(idx)
|
||||||
| rustc_parse_format::ArgumentImplicitlyIs(idx) => {
|
| rustc_parse_format::ArgumentImplicitlyIs(idx) => {
|
||||||
if idx >= operands.len()
|
if idx >= operands.len()
|
||||||
@ -227,7 +236,7 @@ impl ExprCollector<'_> {
|
|||||||
|
|
||||||
if let Some(operand_idx) = operand_idx {
|
if let Some(operand_idx) = operand_idx {
|
||||||
if let Some(position_span) = to_span(arg.position_span) {
|
if let Some(position_span) = to_span(arg.position_span) {
|
||||||
mappings.push((position_span, operand_idx, name));
|
mappings.push((position_span, operand_idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ pub struct OffsetOf {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct InlineAsm {
|
pub struct InlineAsm {
|
||||||
pub operands: Box<[AsmOperand]>,
|
pub operands: Box<[(Option<Name>, AsmOperand)]>,
|
||||||
pub options: AsmOptions,
|
pub options: AsmOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,7 +485,7 @@ impl Expr {
|
|||||||
match self {
|
match self {
|
||||||
Expr::Missing => {}
|
Expr::Missing => {}
|
||||||
Expr::Path(_) | Expr::OffsetOf(_) => {}
|
Expr::Path(_) | Expr::OffsetOf(_) => {}
|
||||||
Expr::InlineAsm(it) => it.operands.iter().for_each(|op| match op {
|
Expr::InlineAsm(it) => it.operands.iter().for_each(|(_, op)| match op {
|
||||||
AsmOperand::In { expr, .. }
|
AsmOperand::In { expr, .. }
|
||||||
| AsmOperand::Out { expr: Some(expr), .. }
|
| AsmOperand::Out { expr: Some(expr), .. }
|
||||||
| AsmOperand::InOut { expr, .. } => f(*expr),
|
| AsmOperand::InOut { expr, .. } => f(*expr),
|
||||||
|
@ -669,7 +669,7 @@ impl InferenceContext<'_> {
|
|||||||
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
|
fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
|
||||||
match &self.body[tgt_expr] {
|
match &self.body[tgt_expr] {
|
||||||
Expr::OffsetOf(_) => (),
|
Expr::OffsetOf(_) => (),
|
||||||
Expr::InlineAsm(e) => e.operands.iter().for_each(|op| match op {
|
Expr::InlineAsm(e) => e.operands.iter().for_each(|(_, op)| match op {
|
||||||
AsmOperand::In { expr, .. }
|
AsmOperand::In { expr, .. }
|
||||||
| AsmOperand::Out { expr: Some(expr), .. }
|
| AsmOperand::Out { expr: Some(expr), .. }
|
||||||
| AsmOperand::InOut { expr, .. } => self.walk_expr_without_adjust(*expr),
|
| AsmOperand::InOut { expr, .. } => self.walk_expr_without_adjust(*expr),
|
||||||
|
@ -956,7 +956,7 @@ impl InferenceContext<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let diverge = asm.options.contains(AsmOptions::NORETURN);
|
let diverge = asm.options.contains(AsmOptions::NORETURN);
|
||||||
asm.operands.iter().for_each(|operand| match *operand {
|
asm.operands.iter().for_each(|(_, operand)| match *operand {
|
||||||
AsmOperand::In { expr, .. } => check_expr_asm_operand(expr, true),
|
AsmOperand::In { expr, .. } => check_expr_asm_operand(expr, true),
|
||||||
AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => {
|
AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => {
|
||||||
check_expr_asm_operand(expr, false)
|
check_expr_asm_operand(expr, false)
|
||||||
|
@ -42,7 +42,7 @@ impl InferenceContext<'_> {
|
|||||||
match &self.body[tgt_expr] {
|
match &self.body[tgt_expr] {
|
||||||
Expr::Missing => (),
|
Expr::Missing => (),
|
||||||
Expr::InlineAsm(e) => {
|
Expr::InlineAsm(e) => {
|
||||||
e.operands.iter().for_each(|op| match op {
|
e.operands.iter().for_each(|(_, op)| match op {
|
||||||
AsmOperand::In { expr, .. }
|
AsmOperand::In { expr, .. }
|
||||||
| AsmOperand::Out { expr: Some(expr), .. }
|
| AsmOperand::Out { expr: Some(expr), .. }
|
||||||
| AsmOperand::InOut { expr, .. } => {
|
| AsmOperand::InOut { expr, .. } => {
|
||||||
|
@ -5259,13 +5259,10 @@ impl InlineAsmOperand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
|
pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
|
||||||
db.body_with_source_map(self.owner)
|
match &db.body(self.owner)[self.expr] {
|
||||||
.1
|
hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
|
||||||
.template_map()?
|
_ => None,
|
||||||
.1
|
}
|
||||||
.get(&self.expr)?
|
|
||||||
.get(self.index)
|
|
||||||
.and_then(|(_, _, name)| name.clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,7 +576,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||||||
let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
|
let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
|
||||||
let res = asm_parts
|
let res = asm_parts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(range, index, _)| {
|
.map(|&(range, index)| {
|
||||||
(
|
(
|
||||||
range + quote.end(),
|
range + quote.end(),
|
||||||
Some(Either::Right(InlineAsmOperand { owner, expr, index })),
|
Some(Either::Right(InlineAsmOperand { owner, expr, index })),
|
||||||
|
@ -913,8 +913,8 @@ impl SourceAnalyzer {
|
|||||||
let (expr, args) = body_source_map.asm_template_args(asm)?;
|
let (expr, args) = body_source_map.asm_template_args(asm)?;
|
||||||
Some(*def).zip(
|
Some(*def).zip(
|
||||||
args.iter()
|
args.iter()
|
||||||
.find(|(range, _, _)| range.contains_inclusive(offset))
|
.find(|(range, _)| range.contains_inclusive(offset))
|
||||||
.map(|(range, idx, _)| (expr, *range, *idx)),
|
.map(|(range, idx)| (expr, *range, *idx)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -944,7 +944,7 @@ impl SourceAnalyzer {
|
|||||||
pub(crate) fn as_asm_parts(
|
pub(crate) fn as_asm_parts(
|
||||||
&self,
|
&self,
|
||||||
asm: InFile<&ast::AsmExpr>,
|
asm: InFile<&ast::AsmExpr>,
|
||||||
) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize, Option<Name>)]))> {
|
) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> {
|
||||||
let (def, _, body_source_map) = self.def.as_ref()?;
|
let (def, _, body_source_map) = self.def.as_ref()?;
|
||||||
Some(*def).zip(body_source_map.asm_template_args(asm))
|
Some(*def).zip(body_source_map.asm_template_args(asm))
|
||||||
}
|
}
|
||||||
|
@ -3008,7 +3008,11 @@ fn test() {
|
|||||||
fn test() {
|
fn test() {
|
||||||
core::arch::asm!(
|
core::arch::asm!(
|
||||||
"push {base$0}",
|
"push {base$0}",
|
||||||
base = const 0
|
"push {base}",
|
||||||
|
boo = const 0,
|
||||||
|
virtual_free = sym VIRTUAL_FREE,
|
||||||
|
base = const 0,
|
||||||
|
boo = const 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
@ -3016,7 +3020,11 @@ fn test() {
|
|||||||
fn test() {
|
fn test() {
|
||||||
core::arch::asm!(
|
core::arch::asm!(
|
||||||
"push {bose}",
|
"push {bose}",
|
||||||
bose = const 0
|
"push {bose}",
|
||||||
|
boo = const 0,
|
||||||
|
virtual_free = sym VIRTUAL_FREE,
|
||||||
|
bose = const 0,
|
||||||
|
boo = const 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user