mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Give InlineAsmOperand a HIR representation
This commit is contained in:
parent
a600e1df73
commit
811905fce8
23 changed files with 409 additions and 217 deletions
|
@ -100,7 +100,14 @@ pub struct BodySourceMap {
|
||||||
field_map_back: FxHashMap<ExprId, FieldSource>,
|
field_map_back: FxHashMap<ExprId, FieldSource>,
|
||||||
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
|
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
|
||||||
|
|
||||||
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
template_map: Option<
|
||||||
|
Box<(
|
||||||
|
// format_args!
|
||||||
|
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
||||||
|
// asm!
|
||||||
|
FxHashMap<ExprId, Vec<(syntax::TextRange, usize)>>,
|
||||||
|
)>,
|
||||||
|
>,
|
||||||
|
|
||||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
|
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
|
||||||
|
|
||||||
|
@ -426,7 +433,16 @@ impl BodySourceMap {
|
||||||
node: InFile<&ast::FormatArgsExpr>,
|
node: InFile<&ast::FormatArgsExpr>,
|
||||||
) -> Option<&[(syntax::TextRange, Name)]> {
|
) -> Option<&[(syntax::TextRange, Name)]> {
|
||||||
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
||||||
self.format_args_template_map.get(self.expr_map.get(&src)?).map(std::ops::Deref::deref)
|
self.template_map.as_ref()?.0.get(self.expr_map.get(&src)?).map(std::ops::Deref::deref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn asm_template_args(
|
||||||
|
&self,
|
||||||
|
node: InFile<&ast::AsmExpr>,
|
||||||
|
) -> Option<(ExprId, &[(syntax::TextRange, usize)])> {
|
||||||
|
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
||||||
|
let expr = self.expr_map.get(&src)?;
|
||||||
|
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to the body source map's diagnostics.
|
/// Get a reference to the body source map's diagnostics.
|
||||||
|
@ -446,11 +462,14 @@ impl BodySourceMap {
|
||||||
field_map_back,
|
field_map_back,
|
||||||
pat_field_map_back,
|
pat_field_map_back,
|
||||||
expansions,
|
expansions,
|
||||||
format_args_template_map,
|
template_map,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
binding_definitions,
|
binding_definitions,
|
||||||
} = self;
|
} = self;
|
||||||
format_args_template_map.shrink_to_fit();
|
if let Some(template_map) = template_map {
|
||||||
|
template_map.0.shrink_to_fit();
|
||||||
|
template_map.1.shrink_to_fit();
|
||||||
|
}
|
||||||
expr_map.shrink_to_fit();
|
expr_map.shrink_to_fit();
|
||||||
expr_map_back.shrink_to_fit();
|
expr_map_back.shrink_to_fit();
|
||||||
pat_map.shrink_to_fit();
|
pat_map.shrink_to_fit();
|
||||||
|
|
|
@ -1847,7 +1847,7 @@ impl ExprCollector<'_> {
|
||||||
},
|
},
|
||||||
syntax_ptr,
|
syntax_ptr,
|
||||||
);
|
);
|
||||||
self.source_map.format_args_template_map.insert(idx, mappings);
|
self.source_map.template_map.get_or_insert_with(Default::default).0.insert(idx, mappings);
|
||||||
idx
|
idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use hir_expand::name::Name;
|
|
||||||
use intern::Symbol;
|
use intern::Symbol;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
|
@ -25,7 +24,7 @@ impl ExprCollector<'_> {
|
||||||
let mut named_pos: FxHashMap<usize, Symbol> = Default::default();
|
let mut named_pos: FxHashMap<usize, Symbol> = Default::default();
|
||||||
let mut named_args: FxHashMap<Symbol, usize> = Default::default();
|
let mut named_args: FxHashMap<Symbol, usize> = Default::default();
|
||||||
let mut reg_args: FxHashSet<usize> = Default::default();
|
let mut reg_args: FxHashSet<usize> = Default::default();
|
||||||
for operand in asm.asm_operands() {
|
for piece in asm.asm_pieces() {
|
||||||
let slot = operands.len();
|
let slot = operands.len();
|
||||||
let mut lower_reg = |reg: Option<ast::AsmRegSpec>| {
|
let mut lower_reg = |reg: Option<ast::AsmRegSpec>| {
|
||||||
let reg = reg?;
|
let reg = reg?;
|
||||||
|
@ -39,14 +38,14 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let op = match operand {
|
let op = match piece {
|
||||||
ast::AsmOperand::AsmClobberAbi(clobber_abi) => {
|
ast::AsmPiece::AsmClobberAbi(clobber_abi) => {
|
||||||
if let Some(abi_name) = clobber_abi.string_token() {
|
if let Some(abi_name) = clobber_abi.string_token() {
|
||||||
clobber_abis.insert(Symbol::intern(abi_name.text()));
|
clobber_abis.insert(Symbol::intern(abi_name.text()));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ast::AsmOperand::AsmOptions(opt) => {
|
ast::AsmPiece::AsmOptions(opt) => {
|
||||||
opt.asm_options().for_each(|opt| {
|
opt.asm_options().for_each(|opt| {
|
||||||
options |= match opt.syntax().first_token().map_or(T![$], |it| it.kind()) {
|
options |= match opt.syntax().first_token().map_or(T![$], |it| it.kind()) {
|
||||||
T![att_syntax] => AsmOptions::ATT_SYNTAX,
|
T![att_syntax] => AsmOptions::ATT_SYNTAX,
|
||||||
|
@ -63,6 +62,14 @@ impl ExprCollector<'_> {
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ast::AsmPiece::AsmOperandNamed(op) => {
|
||||||
|
if let Some(name) = op.name() {
|
||||||
|
let sym = Symbol::intern(&name.text());
|
||||||
|
named_args.insert(sym.clone(), slot);
|
||||||
|
named_pos.insert(slot, sym);
|
||||||
|
}
|
||||||
|
let Some(op) = op.asm_operand() else { continue };
|
||||||
|
match op {
|
||||||
ast::AsmOperand::AsmRegOperand(op) => {
|
ast::AsmOperand::AsmRegOperand(op) => {
|
||||||
let Some(dir_spec) = op.asm_dir_spec() else {
|
let Some(dir_spec) = op.asm_dir_spec() else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -70,22 +77,20 @@ impl ExprCollector<'_> {
|
||||||
let Some(reg) = lower_reg(op.asm_reg_spec()) else {
|
let Some(reg) = lower_reg(op.asm_reg_spec()) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(name) = op.name() {
|
|
||||||
let sym = Symbol::intern(&name.text());
|
|
||||||
named_args.insert(sym.clone(), slot);
|
|
||||||
named_pos.insert(slot, sym);
|
|
||||||
}
|
|
||||||
if dir_spec.in_token().is_some() {
|
if dir_spec.in_token().is_some() {
|
||||||
let expr = self
|
let expr = self.collect_expr_opt(
|
||||||
.collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr()));
|
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
||||||
|
);
|
||||||
AsmOperand::In { reg, expr }
|
AsmOperand::In { reg, expr }
|
||||||
} else if dir_spec.out_token().is_some() {
|
} else if dir_spec.out_token().is_some() {
|
||||||
let expr = self
|
let expr = self.collect_expr_opt(
|
||||||
.collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr()));
|
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
||||||
|
);
|
||||||
AsmOperand::Out { reg, expr: Some(expr), late: false }
|
AsmOperand::Out { reg, expr: Some(expr), late: false }
|
||||||
} else if dir_spec.lateout_token().is_some() {
|
} else if dir_spec.lateout_token().is_some() {
|
||||||
let expr = self
|
let expr = self.collect_expr_opt(
|
||||||
.collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr()));
|
op.asm_operand_expr().and_then(|it| it.in_expr()),
|
||||||
|
);
|
||||||
AsmOperand::Out { reg, expr: Some(expr), late: true }
|
AsmOperand::Out { reg, expr: Some(expr), late: true }
|
||||||
} else if dir_spec.inout_token().is_some() {
|
} else if dir_spec.inout_token().is_some() {
|
||||||
let Some(op_expr) = op.asm_operand_expr() else { continue };
|
let Some(op_expr) = op.asm_operand_expr() else { continue };
|
||||||
|
@ -120,14 +125,19 @@ impl ExprCollector<'_> {
|
||||||
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) => AsmOperand::Const(self.collect_expr_opt(c.expr())),
|
ast::AsmOperand::AsmConst(c) => {
|
||||||
|
AsmOperand::Const(self.collect_expr_opt(c.expr()))
|
||||||
|
}
|
||||||
ast::AsmOperand::AsmSym(s) => {
|
ast::AsmOperand::AsmSym(s) => {
|
||||||
let Some(path) = s.path().and_then(|p| self.expander.parse_path(self.db, p))
|
let Some(path) =
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -192,7 +202,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 = match arg.position {
|
let operand_idx = 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()
|
||||||
|
@ -206,15 +216,15 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
rustc_parse_format::ArgumentNamed(name) => {
|
rustc_parse_format::ArgumentNamed(name) => {
|
||||||
let name = Symbol::intern(name);
|
let name = Symbol::intern(name);
|
||||||
if let Some(position_span) = to_span(arg.position_span) {
|
|
||||||
mappings.push((
|
|
||||||
position_span,
|
|
||||||
Name::new_symbol_root(name.clone()),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
named_args.get(&name).copied()
|
named_args.get(&name).copied()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(operand_idx) = operand_idx {
|
||||||
|
if let Some(position_span) = to_span(arg.position_span) {
|
||||||
|
mappings.push((position_span, operand_idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +234,7 @@ impl ExprCollector<'_> {
|
||||||
Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options }),
|
Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options }),
|
||||||
syntax_ptr,
|
syntax_ptr,
|
||||||
);
|
);
|
||||||
self.source_map.format_args_template_map.insert(idx, mappings);
|
self.source_map.template_map.get_or_insert_with(Default::default).1.insert(idx, mappings);
|
||||||
idx
|
idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ use hir_def::{
|
||||||
body::{BodyDiagnostic, SyntheticSyntax},
|
body::{BodyDiagnostic, SyntheticSyntax},
|
||||||
data::adt::VariantData,
|
data::adt::VariantData,
|
||||||
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
||||||
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
|
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
|
||||||
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
|
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
|
||||||
lang_item::LangItemTarget,
|
lang_item::LangItemTarget,
|
||||||
layout::{self, ReprOptions, TargetDataLayout},
|
layout::{self, ReprOptions, TargetDataLayout},
|
||||||
|
@ -5246,6 +5246,13 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
|
||||||
|
pub struct InlineAsmOperand {
|
||||||
|
owner: DefWithBodyId,
|
||||||
|
expr: ExprId,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Document this
|
// FIXME: Document this
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Callable {
|
pub struct Callable {
|
||||||
|
|
|
@ -47,9 +47,9 @@ use crate::{
|
||||||
source_analyzer::{resolve_hir_path, SourceAnalyzer},
|
source_analyzer::{resolve_hir_path, SourceAnalyzer},
|
||||||
Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
|
Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
|
||||||
ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile,
|
ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile,
|
||||||
ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path,
|
InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name,
|
||||||
ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias,
|
OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField,
|
||||||
TypeParam, Union, Variant, VariantDef,
|
Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
|
||||||
};
|
};
|
||||||
|
|
||||||
const CONTINUE_NO_BREAKS: ControlFlow<Infallible, ()> = ControlFlow::Continue(());
|
const CONTINUE_NO_BREAKS: ControlFlow<Infallible, ()> = ControlFlow::Continue(());
|
||||||
|
@ -546,11 +546,11 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves all the formatting parts of the format_args! template string.
|
/// Retrieves all the formatting parts of the format_args! (or `asm!`) template string.
|
||||||
pub fn as_format_args_parts(
|
pub fn as_format_args_parts(
|
||||||
&self,
|
&self,
|
||||||
string: &ast::String,
|
string: &ast::String,
|
||||||
) -> Option<Vec<(TextRange, Option<PathResolution>)>> {
|
) -> Option<Vec<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)>> {
|
||||||
let quote = string.open_quote_text_range()?;
|
let quote = string.open_quote_text_range()?;
|
||||||
|
|
||||||
let token = self.wrap_token_infile(string.syntax().clone()).into_real_file().ok()?;
|
let token = self.wrap_token_infile(string.syntax().clone()).into_real_file().ok()?;
|
||||||
|
@ -560,14 +560,31 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
let string = ast::String::cast(token)?;
|
let string = ast::String::cast(token)?;
|
||||||
let literal =
|
let literal =
|
||||||
string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
|
string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
|
||||||
let format_args = ast::FormatArgsExpr::cast(literal.parent()?)?;
|
let parent = literal.parent()?;
|
||||||
|
if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) {
|
||||||
let source_analyzer = self.analyze_no_infer(format_args.syntax())?;
|
let source_analyzer = self.analyze_no_infer(format_args.syntax())?;
|
||||||
let format_args = self.wrap_node_infile(format_args);
|
let format_args = self.wrap_node_infile(format_args);
|
||||||
let res = source_analyzer
|
let res = source_analyzer
|
||||||
.as_format_args_parts(self.db, format_args.as_ref())?
|
.as_format_args_parts(self.db, format_args.as_ref())?
|
||||||
.map(|(range, res)| (range + quote.end(), res))
|
.map(|(range, res)| (range + quote.end(), res.map(Either::Left)))
|
||||||
.collect();
|
.collect();
|
||||||
Some(res)
|
Some(res)
|
||||||
|
} else {
|
||||||
|
let asm = ast::AsmExpr::cast(parent)?;
|
||||||
|
let source_analyzer = self.analyze_no_infer(asm.syntax())?;
|
||||||
|
let asm = self.wrap_node_infile(asm);
|
||||||
|
let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
|
||||||
|
let res = asm_parts
|
||||||
|
.iter()
|
||||||
|
.map(|&(range, index)| {
|
||||||
|
(
|
||||||
|
range + quote.end(),
|
||||||
|
Some(Either::Right(InlineAsmOperand { owner, expr, index })),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
})()
|
})()
|
||||||
.map_or(ControlFlow::Continue(()), ControlFlow::Break)
|
.map_or(ControlFlow::Continue(()), ControlFlow::Break)
|
||||||
})
|
})
|
||||||
|
@ -578,7 +595,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
&self,
|
&self,
|
||||||
original_token: SyntaxToken,
|
original_token: SyntaxToken,
|
||||||
offset: TextSize,
|
offset: TextSize,
|
||||||
) -> Option<(TextRange, Option<PathResolution>)> {
|
) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
|
||||||
let original_string = ast::String::cast(original_token.clone())?;
|
let original_string = ast::String::cast(original_token.clone())?;
|
||||||
let original_token = self.wrap_token_infile(original_token).into_real_file().ok()?;
|
let original_token = self.wrap_token_infile(original_token).into_real_file().ok()?;
|
||||||
let quote = original_string.open_quote_text_range()?;
|
let quote = original_string.open_quote_text_range()?;
|
||||||
|
@ -599,13 +616,26 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
&self,
|
&self,
|
||||||
string: ast::String,
|
string: ast::String,
|
||||||
offset: TextSize,
|
offset: TextSize,
|
||||||
) -> Option<(TextRange, Option<PathResolution>)> {
|
) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
|
||||||
debug_assert!(offset <= string.syntax().text_range().len());
|
debug_assert!(offset <= string.syntax().text_range().len());
|
||||||
let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
|
let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
|
||||||
let format_args = ast::FormatArgsExpr::cast(literal.parent()?)?;
|
let parent = literal.parent()?;
|
||||||
|
if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) {
|
||||||
let source_analyzer = &self.analyze_no_infer(format_args.syntax())?;
|
let source_analyzer = &self.analyze_no_infer(format_args.syntax())?;
|
||||||
let format_args = self.wrap_node_infile(format_args);
|
let format_args = self.wrap_node_infile(format_args);
|
||||||
source_analyzer.resolve_offset_in_format_args(self.db, format_args.as_ref(), offset)
|
source_analyzer
|
||||||
|
.resolve_offset_in_format_args(self.db, format_args.as_ref(), offset)
|
||||||
|
.map(|(range, res)| (range, res.map(Either::Left)))
|
||||||
|
} else {
|
||||||
|
let asm = ast::AsmExpr::cast(parent)?;
|
||||||
|
let source_analyzer = &self.analyze_no_infer(asm.syntax())?;
|
||||||
|
let asm = self.wrap_node_infile(asm);
|
||||||
|
source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), offset).map(
|
||||||
|
|(owner, (expr, range, index))| {
|
||||||
|
(range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps a node down by mapping its first and last token down.
|
/// Maps a node down by mapping its first and last token down.
|
||||||
|
@ -1781,6 +1811,7 @@ to_def_impls![
|
||||||
(crate::Label, ast::Label, label_to_def),
|
(crate::Label, ast::Label, label_to_def),
|
||||||
(crate::Adt, ast::Adt, adt_to_def),
|
(crate::Adt, ast::Adt, adt_to_def),
|
||||||
(crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def),
|
(crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def),
|
||||||
|
(crate::InlineAsmOperand, ast::AsmOperandNamed, asm_operand_to_def),
|
||||||
(MacroCallId, ast::MacroCall, macro_call_to_macro_call),
|
(MacroCallId, ast::MacroCall, macro_call_to_macro_call),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -110,7 +110,7 @@ use syntax::{
|
||||||
AstNode, AstPtr, SyntaxNode,
|
AstNode, AstPtr, SyntaxNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{db::HirDatabase, InFile};
|
use crate::{db::HirDatabase, InFile, InlineAsmOperand};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct SourceToDefCache {
|
pub(super) struct SourceToDefCache {
|
||||||
|
@ -273,6 +273,25 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
ast::Adt::Union(it) => self.union_to_def(InFile::new(file_id, it)).map(AdtId::UnionId),
|
ast::Adt::Union(it) => self.union_to_def(InFile::new(file_id, it)).map(AdtId::UnionId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn asm_operand_to_def(
|
||||||
|
&mut self,
|
||||||
|
src: InFile<&ast::AsmOperandNamed>,
|
||||||
|
) -> Option<InlineAsmOperand> {
|
||||||
|
let asm = src.value.syntax().parent().and_then(ast::AsmExpr::cast)?;
|
||||||
|
let index = asm
|
||||||
|
.asm_pieces()
|
||||||
|
.filter_map(|it| match it {
|
||||||
|
ast::AsmPiece::AsmOperandNamed(it) => Some(it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.position(|it| it == *src.value)?;
|
||||||
|
let container = self.find_pat_or_label_container(src.syntax_ref())?;
|
||||||
|
let (_, source_map) = self.db.body_with_source_map(container);
|
||||||
|
let expr = source_map.node_expr(src.with_value(&ast::Expr::AsmExpr(asm)))?;
|
||||||
|
Some(InlineAsmOperand { owner: container, expr, index })
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn bind_pat_to_def(
|
pub(super) fn bind_pat_to_def(
|
||||||
&mut self,
|
&mut self,
|
||||||
src: InFile<&ast::IdentPat>,
|
src: InFile<&ast::IdentPat>,
|
||||||
|
|
|
@ -904,6 +904,20 @@ impl SourceAnalyzer {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn resolve_offset_in_asm_template(
|
||||||
|
&self,
|
||||||
|
asm: InFile<&ast::AsmExpr>,
|
||||||
|
offset: TextSize,
|
||||||
|
) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> {
|
||||||
|
let (def, _, body_source_map) = self.def.as_ref()?;
|
||||||
|
let (expr, args) = body_source_map.asm_template_args(asm)?;
|
||||||
|
Some(*def).zip(
|
||||||
|
args.iter()
|
||||||
|
.find(|(range, _)| range.contains_inclusive(offset))
|
||||||
|
.map(|(range, idx)| (expr, *range, *idx)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn as_format_args_parts<'a>(
|
pub(crate) fn as_format_args_parts<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
db: &'a dyn HirDatabase,
|
db: &'a dyn HirDatabase,
|
||||||
|
@ -927,6 +941,14 @@ impl SourceAnalyzer {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_asm_parts(
|
||||||
|
&self,
|
||||||
|
asm: InFile<&ast::AsmExpr>,
|
||||||
|
) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> {
|
||||||
|
let (def, _, body_source_map) = self.def.as_ref()?;
|
||||||
|
Some(*def).zip(body_source_map.asm_template_args(asm))
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_impl_method_or_trait_def(
|
fn resolve_impl_method_or_trait_def(
|
||||||
&self,
|
&self,
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
|
|
|
@ -10,8 +10,8 @@ use either::Either;
|
||||||
use hir::{
|
use hir::{
|
||||||
Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
|
Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
|
||||||
Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
|
Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
|
||||||
Function, GenericParam, HasVisibility, HirDisplay, Impl, Label, Local, Macro, Module,
|
Function, GenericParam, HasVisibility, HirDisplay, Impl, InlineAsmOperand, Label, Local, Macro,
|
||||||
ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait,
|
Module, ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait,
|
||||||
TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
|
TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
|
||||||
};
|
};
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
|
@ -51,7 +51,7 @@ pub enum Definition {
|
||||||
ToolModule(ToolModule),
|
ToolModule(ToolModule),
|
||||||
ExternCrateDecl(ExternCrateDecl),
|
ExternCrateDecl(ExternCrateDecl),
|
||||||
InlineAsmRegOrRegClass(()),
|
InlineAsmRegOrRegClass(()),
|
||||||
InlineAsmRegOperand(()),
|
InlineAsmOperand(InlineAsmOperand),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Definition {
|
impl Definition {
|
||||||
|
@ -91,7 +91,7 @@ impl Definition {
|
||||||
| Definition::TupleField(_)
|
| Definition::TupleField(_)
|
||||||
| Definition::ToolModule(_)
|
| Definition::ToolModule(_)
|
||||||
| Definition::InlineAsmRegOrRegClass(_)
|
| Definition::InlineAsmRegOrRegClass(_)
|
||||||
| Definition::InlineAsmRegOperand(_) => return None,
|
| Definition::InlineAsmOperand(_) => return None,
|
||||||
};
|
};
|
||||||
Some(module)
|
Some(module)
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ impl Definition {
|
||||||
| Definition::Label(_)
|
| Definition::Label(_)
|
||||||
| Definition::DeriveHelper(_)
|
| Definition::DeriveHelper(_)
|
||||||
| Definition::InlineAsmRegOrRegClass(_)
|
| Definition::InlineAsmRegOrRegClass(_)
|
||||||
| Definition::InlineAsmRegOperand(_) => return None,
|
| Definition::InlineAsmOperand(_) => return None,
|
||||||
};
|
};
|
||||||
Some(vis)
|
Some(vis)
|
||||||
}
|
}
|
||||||
|
@ -156,9 +156,7 @@ impl Definition {
|
||||||
Definition::ToolModule(_) => return None, // FIXME
|
Definition::ToolModule(_) => return None, // FIXME
|
||||||
Definition::DeriveHelper(it) => it.name(db),
|
Definition::DeriveHelper(it) => it.name(db),
|
||||||
Definition::ExternCrateDecl(it) => return it.alias_or_name(db),
|
Definition::ExternCrateDecl(it) => return it.alias_or_name(db),
|
||||||
Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmRegOperand(_) => {
|
Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmOperand(_) => return None, // FIXME
|
||||||
return None
|
|
||||||
} // FIXME
|
|
||||||
};
|
};
|
||||||
Some(name)
|
Some(name)
|
||||||
}
|
}
|
||||||
|
@ -221,7 +219,7 @@ impl Definition {
|
||||||
Definition::ToolModule(_) => None,
|
Definition::ToolModule(_) => None,
|
||||||
Definition::DeriveHelper(_) => None,
|
Definition::DeriveHelper(_) => None,
|
||||||
Definition::TupleField(_) => None,
|
Definition::TupleField(_) => None,
|
||||||
Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmRegOperand(_) => None,
|
Definition::InlineAsmRegOrRegClass(_) | Definition::InlineAsmOperand(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
docs.or_else(|| {
|
docs.or_else(|| {
|
||||||
|
@ -280,7 +278,7 @@ impl Definition {
|
||||||
}
|
}
|
||||||
// FIXME
|
// FIXME
|
||||||
Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(),
|
Definition::InlineAsmRegOrRegClass(_) => "inline_asm_reg_or_reg_class".to_owned(),
|
||||||
Definition::InlineAsmRegOperand(_) => "inline_asm_reg_operand".to_owned(),
|
Definition::InlineAsmOperand(_) => "inline_asm_reg_operand".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,7 +440,6 @@ impl NameClass {
|
||||||
let _p = tracing::info_span!("NameClass::classify").entered();
|
let _p = tracing::info_span!("NameClass::classify").entered();
|
||||||
|
|
||||||
let parent = name.syntax().parent()?;
|
let parent = name.syntax().parent()?;
|
||||||
|
|
||||||
let definition = match_ast! {
|
let definition = match_ast! {
|
||||||
match parent {
|
match parent {
|
||||||
ast::Item(it) => classify_item(sema, it)?,
|
ast::Item(it) => classify_item(sema, it)?,
|
||||||
|
@ -453,6 +450,7 @@ impl NameClass {
|
||||||
ast::Variant(it) => Definition::Variant(sema.to_def(&it)?),
|
ast::Variant(it) => Definition::Variant(sema.to_def(&it)?),
|
||||||
ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
|
ast::TypeParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
|
||||||
ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
|
ast::ConstParam(it) => Definition::GenericParam(sema.to_def(&it)?.into()),
|
||||||
|
ast::AsmOperandNamed(it) => Definition::InlineAsmOperand(sema.to_def(&it)?),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -769,6 +767,18 @@ impl From<Impl> for Definition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<InlineAsmOperand> for Definition {
|
||||||
|
fn from(value: InlineAsmOperand) -> Self {
|
||||||
|
Definition::InlineAsmOperand(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Either<PathResolution, InlineAsmOperand>> for Definition {
|
||||||
|
fn from(value: Either<PathResolution, InlineAsmOperand>) -> Self {
|
||||||
|
value.either(Definition::from, Definition::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsAssocItem for Definition {
|
impl AsAssocItem for Definition {
|
||||||
fn as_assoc_item(self, db: &dyn hir::db::HirDatabase) -> Option<AssocItem> {
|
fn as_assoc_item(self, db: &dyn hir::db::HirDatabase) -> Option<AssocItem> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -208,7 +208,7 @@ impl Definition {
|
||||||
| Definition::TupleField(_)
|
| Definition::TupleField(_)
|
||||||
| Definition::InlineAsmRegOrRegClass(_) => return None,
|
| Definition::InlineAsmRegOrRegClass(_) => return None,
|
||||||
// FIXME:
|
// FIXME:
|
||||||
Definition::InlineAsmRegOperand(_) => return None,
|
Definition::InlineAsmOperand(_) => return None,
|
||||||
// FIXME: This should be doable in theory
|
// FIXME: This should be doable in theory
|
||||||
Definition::DeriveHelper(_) => return None,
|
Definition::DeriveHelper(_) => return None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,10 +8,11 @@ use std::mem;
|
||||||
use std::{cell::LazyCell, cmp::Reverse};
|
use std::{cell::LazyCell, cmp::Reverse};
|
||||||
|
|
||||||
use base_db::{salsa::Database, SourceDatabase, SourceRootDatabase};
|
use base_db::{salsa::Database, SourceDatabase, SourceRootDatabase};
|
||||||
|
use either::Either;
|
||||||
use hir::{
|
use hir::{
|
||||||
sym, Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer,
|
sym, Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer,
|
||||||
HasSource, HirFileIdExt, InFile, InFileWrapper, InRealFile, ItemContainer, ModuleSource,
|
HasSource, HirFileIdExt, InFile, InFileWrapper, InRealFile, InlineAsmOperand, ItemContainer,
|
||||||
PathResolution, Semantics, Visibility,
|
ModuleSource, PathResolution, Semantics, Visibility,
|
||||||
};
|
};
|
||||||
use memchr::memmem::Finder;
|
use memchr::memmem::Finder;
|
||||||
use parser::SyntaxKind;
|
use parser::SyntaxKind;
|
||||||
|
@ -917,7 +918,7 @@ impl<'a> FindUsages<'a> {
|
||||||
for offset in Self::match_indices(&text, finder, search_range) {
|
for offset in Self::match_indices(&text, finder, search_range) {
|
||||||
tree.token_at_offset(offset).for_each(|token| {
|
tree.token_at_offset(offset).for_each(|token| {
|
||||||
let Some(str_token) = ast::String::cast(token.clone()) else { return };
|
let Some(str_token) = ast::String::cast(token.clone()) else { return };
|
||||||
if let Some((range, nameres)) =
|
if let Some((range, Some(nameres))) =
|
||||||
sema.check_for_format_args_template(token, offset)
|
sema.check_for_format_args_template(token, offset)
|
||||||
{
|
{
|
||||||
if self.found_format_args_ref(file_id, range, str_token, nameres, sink) {}
|
if self.found_format_args_ref(file_id, range, str_token, nameres, sink) {}
|
||||||
|
@ -1087,19 +1088,19 @@ impl<'a> FindUsages<'a> {
|
||||||
file_id: EditionedFileId,
|
file_id: EditionedFileId,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
token: ast::String,
|
token: ast::String,
|
||||||
res: Option<PathResolution>,
|
res: Either<PathResolution, InlineAsmOperand>,
|
||||||
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
|
sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match res.map(Definition::from) {
|
let def = res.either(Definition::from, Definition::from);
|
||||||
Some(def) if def == self.def => {
|
if def == self.def {
|
||||||
let reference = FileReference {
|
let reference = FileReference {
|
||||||
range,
|
range,
|
||||||
name: FileReferenceNode::FormatStringEntry(token, range),
|
name: FileReferenceNode::FormatStringEntry(token, range),
|
||||||
category: ReferenceCategory::READ,
|
category: ReferenceCategory::READ,
|
||||||
};
|
};
|
||||||
sink(file_id, reference)
|
sink(file_id, reference)
|
||||||
}
|
} else {
|
||||||
_ => false,
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,7 +221,7 @@ pub(crate) fn resolve_doc_path_for_def(
|
||||||
| Definition::Label(_)
|
| Definition::Label(_)
|
||||||
| Definition::DeriveHelper(_)
|
| Definition::DeriveHelper(_)
|
||||||
| Definition::InlineAsmRegOrRegClass(_)
|
| Definition::InlineAsmRegOrRegClass(_)
|
||||||
| Definition::InlineAsmRegOperand(_) => None,
|
| Definition::InlineAsmOperand(_) => None,
|
||||||
}
|
}
|
||||||
.map(Definition::from)
|
.map(Definition::from)
|
||||||
}
|
}
|
||||||
|
@ -676,7 +676,7 @@ fn filename_and_frag_for_def(
|
||||||
| Definition::ToolModule(_)
|
| Definition::ToolModule(_)
|
||||||
| Definition::DeriveHelper(_)
|
| Definition::DeriveHelper(_)
|
||||||
| Definition::InlineAsmRegOrRegClass(_)
|
| Definition::InlineAsmRegOrRegClass(_)
|
||||||
| Definition::InlineAsmRegOperand(_) => return None,
|
| Definition::InlineAsmOperand(_) => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((def, res, None))
|
Some((def, res, None))
|
||||||
|
|
|
@ -223,7 +223,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati
|
||||||
Variable
|
Variable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Definition::Label(..) | Definition::InlineAsmRegOperand(_) => Variable, // For lack of a better variant
|
Definition::Label(..) | Definition::InlineAsmOperand(_) => Variable, // For lack of a better variant
|
||||||
Definition::DeriveHelper(..) => Attribute,
|
Definition::DeriveHelper(..) => Attribute,
|
||||||
Definition::BuiltinAttr(..) => Attribute,
|
Definition::BuiltinAttr(..) => Attribute,
|
||||||
Definition::ToolModule(..) => Module,
|
Definition::ToolModule(..) => Module,
|
||||||
|
@ -323,7 +323,7 @@ pub(crate) fn def_to_moniker(
|
||||||
| Definition::BuiltinAttr(_)
|
| Definition::BuiltinAttr(_)
|
||||||
| Definition::ToolModule(_)
|
| Definition::ToolModule(_)
|
||||||
| Definition::InlineAsmRegOrRegClass(_)
|
| Definition::InlineAsmRegOrRegClass(_)
|
||||||
| Definition::InlineAsmRegOperand(_) => return None,
|
| Definition::InlineAsmOperand(_) => return None,
|
||||||
|
|
||||||
Definition::Local(local) => {
|
Definition::Local(local) => {
|
||||||
if !local.is_param(db) {
|
if !local.is_param(db) {
|
||||||
|
|
|
@ -245,7 +245,7 @@ impl TryToNav for Definition {
|
||||||
| Definition::InlineAsmRegOrRegClass(_)
|
| Definition::InlineAsmRegOrRegClass(_)
|
||||||
| Definition::BuiltinAttr(_) => None,
|
| Definition::BuiltinAttr(_) => None,
|
||||||
// FIXME
|
// FIXME
|
||||||
Definition::InlineAsmRegOperand(_) => None,
|
Definition::InlineAsmOperand(_) => None,
|
||||||
// FIXME: The focus range should be set to the helper declaration
|
// FIXME: The focus range should be set to the helper declaration
|
||||||
Definition::DeriveHelper(it) => it.derive().try_to_nav(db),
|
Definition::DeriveHelper(it) => it.derive().try_to_nav(db),
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@ pub(super) fn highlight_format_string(
|
||||||
expanded_string: &ast::String,
|
expanded_string: &ast::String,
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
) {
|
) {
|
||||||
if !is_format_string(expanded_string) {
|
if is_format_string(expanded_string) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Replace this with the HIR info we have now.
|
// FIXME: Replace this with the HIR info we have now.
|
||||||
lex_format_specifiers(string, &mut |piece_range, kind| {
|
lex_format_specifiers(string, &mut |piece_range, kind| {
|
||||||
if let Some(highlight) = highlight_format_specifier(kind) {
|
if let Some(highlight) = highlight_format_specifier(kind) {
|
||||||
|
@ -34,6 +31,9 @@ pub(super) fn highlight_format_string(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(parts) = sema.as_format_args_parts(string) {
|
if let Some(parts) = sema.as_format_args_parts(string) {
|
||||||
parts.into_iter().for_each(|(range, res)| {
|
parts.into_iter().for_each(|(range, res)| {
|
||||||
if let Some(res) = res {
|
if let Some(res) = res {
|
||||||
|
|
|
@ -537,7 +537,7 @@ pub(super) fn highlight_def(
|
||||||
Definition::InlineAsmRegOrRegClass(_) => {
|
Definition::InlineAsmRegOrRegClass(_) => {
|
||||||
Highlight::new(HlTag::Symbol(SymbolKind::InlineAsmRegOrRegClass))
|
Highlight::new(HlTag::Symbol(SymbolKind::InlineAsmRegOrRegClass))
|
||||||
}
|
}
|
||||||
Definition::InlineAsmRegOperand(_) => Highlight::new(HlTag::Symbol(SymbolKind::Local)),
|
Definition::InlineAsmOperand(_) => Highlight::new(HlTag::Symbol(SymbolKind::Local)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let def_crate = def.krate(db);
|
let def_crate = def.krate(db);
|
||||||
|
|
|
@ -316,7 +316,7 @@ fn module_def_to_hl_tag(def: Definition) -> HlTag {
|
||||||
Definition::ToolModule(_) => SymbolKind::ToolModule,
|
Definition::ToolModule(_) => SymbolKind::ToolModule,
|
||||||
Definition::DeriveHelper(_) => SymbolKind::DeriveHelper,
|
Definition::DeriveHelper(_) => SymbolKind::DeriveHelper,
|
||||||
Definition::InlineAsmRegOrRegClass(_) => SymbolKind::InlineAsmRegOrRegClass,
|
Definition::InlineAsmRegOrRegClass(_) => SymbolKind::InlineAsmRegOrRegClass,
|
||||||
Definition::InlineAsmRegOperand(_) => SymbolKind::Local,
|
Definition::InlineAsmOperand(_) => SymbolKind::Local,
|
||||||
};
|
};
|
||||||
HlTag::Symbol(symbol)
|
HlTag::Symbol(symbol)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,17 +50,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">o</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">o</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
|
||||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
|
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
|
||||||
<span class="string_literal macro">"%input = OpLoad _ {0}"</span><span class="comma macro">,</span>
|
<span class="string_literal macro">"%input = </span><span class="variable library">O</span><span class="string_literal macro">pLoad _ {</span><span class="variable library">0</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||||
<span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"%result = "</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="string_literal macro">" _ %input"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
<span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"%result = "</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="string_literal macro">" _ %input"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
||||||
<span class="string_literal macro">"OpStore {1} %result"</span><span class="comma macro">,</span>
|
<span class="string_literal macro">"OpStore {</span><span class="variable library">1</span><span class="string_literal macro">} %result</span><span class="variable library">"</span><span class="comma macro">,</span>
|
||||||
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="variable macro">foo</span><span class="comma macro">,</span>
|
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="variable macro">foo</span><span class="comma macro">,</span>
|
||||||
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="keyword macro">mut</span> <span class="variable macro mutable">o</span><span class="comma macro">,</span>
|
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="keyword macro">mut</span> <span class="variable macro mutable">o</span><span class="comma macro">,</span>
|
||||||
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="keyword">let</span> <span class="variable declaration">thread_id</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration">thread_id</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
|
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
|
||||||
mov {0}, gs:[0x30]
|
mov {</span><span class="variable library">0</span><span class="string_literal macro">}, gs:[0x30]
|
||||||
mov {0}, [{0}+0x48]
|
mov {</span><span class="variable library">0</span><span class="string_literal macro">}, [{</span><span class="variable library">0</span><span class="string_literal macro">}+0x48]
|
||||||
"</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
"</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="keyword">static</span> <span class="static declaration">UNMAP_BASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
<span class="keyword">static</span> <span class="static declaration">UNMAP_BASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||||
|
@ -69,28 +69,28 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="keyword const">const</span> <span class="constant const declaration">OffPtr</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
<span class="keyword const">const</span> <span class="constant const declaration">OffPtr</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||||
<span class="keyword const">const</span> <span class="constant const declaration">OffFn</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
<span class="keyword const">const</span> <span class="constant const declaration">OffFn</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
|
||||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
|
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
|
||||||
push {free_type}
|
push {</span><span class="variable library">free_type</span><span class="string_literal macro">}
|
||||||
push {free_size}
|
push {</span><span class="variable library">free_size</span><span class="string_literal macro">}
|
||||||
push {base}
|
push {</span><span class="variable library">base</span><span class="string_literal macro">}
|
||||||
|
|
||||||
mov eax, fs:[30h]
|
mov eax, fs:[30h]
|
||||||
mov eax, [eax+8h]
|
mov eax, [eax+8h]
|
||||||
add eax, {off_fn}
|
add eax, {</span><span class="variable library">off_fn</span><span class="string_literal macro">}
|
||||||
mov [eax-{off_fn}+{off_ptr}], eax
|
mov [eax-{</span><span class="variable library">off_fn</span><span class="string_literal macro">}+{</span><span class="variable library">off_ptr</span><span class="string_literal macro">}], eax
|
||||||
|
|
||||||
push eax
|
push eax
|
||||||
|
|
||||||
jmp {virtual_free}
|
jmp {</span><span class="variable library">virtual_free</span><span class="string_literal macro">}
|
||||||
"</span><span class="comma macro">,</span>
|
"</span><span class="comma macro">,</span>
|
||||||
<span class="unresolved_reference declaration macro">off_ptr</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">OffPtr</span><span class="comma macro">,</span>
|
<span class="variable declaration library macro">off_ptr</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">OffPtr</span><span class="comma macro">,</span>
|
||||||
<span class="unresolved_reference declaration macro">off_fn</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">OffFn</span><span class="comma macro">,</span>
|
<span class="variable declaration library macro">off_fn</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">OffFn</span><span class="comma macro">,</span>
|
||||||
|
|
||||||
<span class="unresolved_reference declaration macro">free_size</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="numeric_literal macro">0</span><span class="comma macro">,</span>
|
<span class="variable declaration library macro">free_size</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="numeric_literal macro">0</span><span class="comma macro">,</span>
|
||||||
<span class="unresolved_reference declaration macro">free_type</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">MEM_RELEASE</span><span class="comma macro">,</span>
|
<span class="variable declaration library macro">free_type</span> <span class="operator macro">=</span> <span class="keyword macro">const</span> <span class="constant const macro">MEM_RELEASE</span><span class="comma macro">,</span>
|
||||||
|
|
||||||
<span class="unresolved_reference declaration macro">virtual_free</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">VirtualFree</span><span class="comma macro">,</span>
|
<span class="variable declaration library macro">virtual_free</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">VirtualFree</span><span class="comma macro">,</span>
|
||||||
|
|
||||||
<span class="unresolved_reference declaration macro">base</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">UNMAP_BASE</span><span class="comma macro">,</span>
|
<span class="variable declaration library macro">base</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">UNMAP_BASE</span><span class="comma macro">,</span>
|
||||||
<span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
<span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
|
||||||
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="brace">}</span>
|
<span class="brace">}</span>
|
||||||
|
|
|
@ -166,8 +166,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
|
||||||
<span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
|
||||||
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
|
<span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
|
||||||
<span class="string_literal macro">"mov {0}, {1}"</span><span class="comma macro">,</span>
|
<span class="string_literal macro">"mov {</span><span class="variable library">0</span><span class="string_literal macro">}, {</span><span class="variable library">1</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||||
<span class="string_literal macro">"add {0}, 5"</span><span class="comma macro">,</span>
|
<span class="string_literal macro">"add {</span><span class="variable library">0</span><span class="string_literal macro">}, 5</span><span class="variable library">"</span><span class="comma macro">,</span>
|
||||||
<span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">o</span><span class="comma macro">,</span>
|
<span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">o</span><span class="comma macro">,</span>
|
||||||
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">i</span><span class="comma macro">,</span>
|
<span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">i</span><span class="comma macro">,</span>
|
||||||
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
@ -175,6 +175,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
|
<span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
|
||||||
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable reference">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="constant const">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable mutable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable reference">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="brace">}</span></code></pre>
|
<span class="brace">}</span></code></pre>
|
|
@ -329,11 +329,11 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let op = p.start();
|
let op_n = p.start();
|
||||||
// Parse clobber_abi
|
// Parse clobber_abi
|
||||||
if p.eat_contextual_kw(T![clobber_abi]) {
|
if p.eat_contextual_kw(T![clobber_abi]) {
|
||||||
parse_clobber_abi(p);
|
parse_clobber_abi(p);
|
||||||
op.complete(p, ASM_CLOBBER_ABI);
|
op_n.complete(p, ASM_CLOBBER_ABI);
|
||||||
allow_templates = false;
|
allow_templates = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
|
||||||
// Parse options
|
// Parse options
|
||||||
if p.eat_contextual_kw(T![options]) {
|
if p.eat_contextual_kw(T![options]) {
|
||||||
parse_options(p);
|
parse_options(p);
|
||||||
op.complete(p, ASM_OPTIONS);
|
op_n.complete(p, ASM_OPTIONS);
|
||||||
allow_templates = false;
|
allow_templates = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -356,12 +356,14 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let op = p.start();
|
||||||
let dir_spec = p.start();
|
let dir_spec = p.start();
|
||||||
if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) {
|
if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) {
|
||||||
dir_spec.complete(p, ASM_DIR_SPEC);
|
dir_spec.complete(p, ASM_DIR_SPEC);
|
||||||
parse_reg(p);
|
parse_reg(p);
|
||||||
expr(p);
|
expr(p);
|
||||||
op.complete(p, ASM_REG_OPERAND);
|
op.complete(p, ASM_REG_OPERAND);
|
||||||
|
op_n.complete(p, ASM_OPERAND_NAMED);
|
||||||
} else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) {
|
} else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) {
|
||||||
dir_spec.complete(p, ASM_DIR_SPEC);
|
dir_spec.complete(p, ASM_DIR_SPEC);
|
||||||
parse_reg(p);
|
parse_reg(p);
|
||||||
|
@ -370,21 +372,26 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
|
||||||
expr(p);
|
expr(p);
|
||||||
}
|
}
|
||||||
op.complete(p, ASM_REG_OPERAND);
|
op.complete(p, ASM_REG_OPERAND);
|
||||||
|
op_n.complete(p, ASM_OPERAND_NAMED);
|
||||||
} else if p.eat_contextual_kw(T![label]) {
|
} else if p.eat_contextual_kw(T![label]) {
|
||||||
dir_spec.abandon(p);
|
dir_spec.abandon(p);
|
||||||
block_expr(p);
|
block_expr(p);
|
||||||
op.complete(p, ASM_LABEL);
|
op.complete(p, ASM_OPERAND_NAMED);
|
||||||
|
op_n.complete(p, ASM_LABEL);
|
||||||
} else if p.eat(T![const]) {
|
} else if p.eat(T![const]) {
|
||||||
dir_spec.abandon(p);
|
dir_spec.abandon(p);
|
||||||
expr(p);
|
expr(p);
|
||||||
op.complete(p, ASM_CONST);
|
op.complete(p, ASM_CONST);
|
||||||
|
op_n.complete(p, ASM_OPERAND_NAMED);
|
||||||
} else if p.eat_contextual_kw(T![sym]) {
|
} else if p.eat_contextual_kw(T![sym]) {
|
||||||
dir_spec.abandon(p);
|
dir_spec.abandon(p);
|
||||||
paths::type_path(p);
|
paths::type_path(p);
|
||||||
op.complete(p, ASM_SYM);
|
op.complete(p, ASM_SYM);
|
||||||
|
op_n.complete(p, ASM_OPERAND_NAMED);
|
||||||
} else if allow_templates {
|
} else if allow_templates {
|
||||||
dir_spec.abandon(p);
|
dir_spec.abandon(p);
|
||||||
op.abandon(p);
|
op.abandon(p);
|
||||||
|
op_n.abandon(p);
|
||||||
if expr(p).is_none() {
|
if expr(p).is_none() {
|
||||||
p.err_and_bump("expected asm template");
|
p.err_and_bump("expected asm template");
|
||||||
}
|
}
|
||||||
|
@ -392,6 +399,7 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
|
||||||
} else {
|
} else {
|
||||||
dir_spec.abandon(p);
|
dir_spec.abandon(p);
|
||||||
op.abandon(p);
|
op.abandon(p);
|
||||||
|
op_n.abandon(p);
|
||||||
p.err_and_bump("expected asm operand");
|
p.err_and_bump("expected asm operand");
|
||||||
if p.at(T!['}']) {
|
if p.at(T!['}']) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -169,8 +169,10 @@ pub enum SyntaxKind {
|
||||||
ASM_LABEL,
|
ASM_LABEL,
|
||||||
ASM_OPERAND,
|
ASM_OPERAND,
|
||||||
ASM_OPERAND_EXPR,
|
ASM_OPERAND_EXPR,
|
||||||
|
ASM_OPERAND_NAMED,
|
||||||
ASM_OPTION,
|
ASM_OPTION,
|
||||||
ASM_OPTIONS,
|
ASM_OPTIONS,
|
||||||
|
ASM_PIECE,
|
||||||
ASM_REG_OPERAND,
|
ASM_REG_OPERAND,
|
||||||
ASM_REG_SPEC,
|
ASM_REG_SPEC,
|
||||||
ASM_SYM,
|
ASM_SYM,
|
||||||
|
|
|
@ -35,12 +35,13 @@ SOURCE_FILE
|
||||||
STRING "\"add {x}, {tmp}\""
|
STRING "\"add {x}, {tmp}\""
|
||||||
COMMA ","
|
COMMA ","
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
ASM_REG_OPERAND
|
ASM_OPERAND_NAMED
|
||||||
NAME
|
NAME
|
||||||
IDENT "x"
|
IDENT "x"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
EQ "="
|
EQ "="
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
ASM_REG_OPERAND
|
||||||
ASM_DIR_SPEC
|
ASM_DIR_SPEC
|
||||||
INOUT_KW "inout"
|
INOUT_KW "inout"
|
||||||
L_PAREN "("
|
L_PAREN "("
|
||||||
|
@ -56,12 +57,13 @@ SOURCE_FILE
|
||||||
IDENT "x"
|
IDENT "x"
|
||||||
COMMA ","
|
COMMA ","
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
ASM_REG_OPERAND
|
ASM_OPERAND_NAMED
|
||||||
NAME
|
NAME
|
||||||
IDENT "tmp"
|
IDENT "tmp"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
EQ "="
|
EQ "="
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
|
ASM_REG_OPERAND
|
||||||
ASM_DIR_SPEC
|
ASM_DIR_SPEC
|
||||||
OUT_KW "out"
|
OUT_KW "out"
|
||||||
L_PAREN "("
|
L_PAREN "("
|
||||||
|
|
|
@ -395,7 +395,7 @@ OffsetOfExpr =
|
||||||
// global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")"
|
// global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")"
|
||||||
// format_string := STRING_LITERAL / RAW_STRING_LITERAL
|
// format_string := STRING_LITERAL / RAW_STRING_LITERAL
|
||||||
AsmExpr =
|
AsmExpr =
|
||||||
Attr* 'builtin' '#' 'asm' '(' template:(Expr (',' Expr)*) (AsmOperand (',' AsmOperand)*)? ','? ')'
|
Attr* 'builtin' '#' 'asm' '(' template:(Expr (',' Expr)*) (AsmPiece (',' AsmPiece)*)? ','? ')'
|
||||||
|
|
||||||
// operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
|
// operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
|
||||||
AsmOperandExpr = in_expr:Expr ('=>' out_expr:Expr)?
|
AsmOperandExpr = in_expr:Expr ('=>' out_expr:Expr)?
|
||||||
|
@ -404,7 +404,7 @@ AsmDirSpec = 'in' | 'out' | 'lateout' | 'inout' | 'inlateout'
|
||||||
// reg_spec := <register class> / "\"" <explicit register> "\""
|
// reg_spec := <register class> / "\"" <explicit register> "\""
|
||||||
AsmRegSpec = '@string' | NameRef
|
AsmRegSpec = '@string' | NameRef
|
||||||
// reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr
|
// reg_operand := [ident "="] dir_spec "(" reg_spec ")" operand_expr
|
||||||
AsmRegOperand = (Name '=')? AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr
|
AsmRegOperand = AsmDirSpec '(' AsmRegSpec ')' AsmOperandExpr
|
||||||
// clobber_abi := "clobber_abi(" <abi> *("," <abi>) [","] ")"
|
// clobber_abi := "clobber_abi(" <abi> *("," <abi>) [","] ")"
|
||||||
AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')'
|
AsmClobberAbi = 'clobber_abi' '(' ('@string' (',' '@string')* ','?) ')'
|
||||||
// option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
|
// option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw"
|
||||||
|
@ -415,7 +415,9 @@ AsmLabel = 'label' BlockExpr
|
||||||
AsmSym = 'sym' Path
|
AsmSym = 'sym' Path
|
||||||
AsmConst = 'const' Expr
|
AsmConst = 'const' Expr
|
||||||
// operand := reg_operand / clobber_abi / options
|
// operand := reg_operand / clobber_abi / options
|
||||||
AsmOperand = AsmRegOperand | AsmClobberAbi | AsmOptions | AsmLabel | AsmSym | AsmConst
|
AsmOperand = AsmRegOperand | AsmLabel | AsmSym | AsmConst
|
||||||
|
AsmOperandNamed = (Name '=')? AsmOperand
|
||||||
|
AsmPiece = AsmOperandNamed | AsmClobberAbi | AsmOptions
|
||||||
|
|
||||||
FormatArgsExpr =
|
FormatArgsExpr =
|
||||||
Attr* 'builtin' '#' 'format_args' '('
|
Attr* 'builtin' '#' 'format_args' '('
|
||||||
|
|
|
@ -118,7 +118,7 @@ pub struct AsmExpr {
|
||||||
impl ast::HasAttrs for AsmExpr {}
|
impl ast::HasAttrs for AsmExpr {}
|
||||||
impl AsmExpr {
|
impl AsmExpr {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn asm_operands(&self) -> AstChildren<AsmOperand> { support::children(&self.syntax) }
|
pub fn asm_pieces(&self) -> AstChildren<AsmPiece> { support::children(&self.syntax) }
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn template(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
|
pub fn template(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -159,6 +159,18 @@ impl AsmOperandExpr {
|
||||||
pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
|
pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct AsmOperandNamed {
|
||||||
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
}
|
||||||
|
impl ast::HasName for AsmOperandNamed {}
|
||||||
|
impl AsmOperandNamed {
|
||||||
|
#[inline]
|
||||||
|
pub fn asm_operand(&self) -> Option<AsmOperand> { support::child(&self.syntax) }
|
||||||
|
#[inline]
|
||||||
|
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct AsmOption {
|
pub struct AsmOption {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
@ -217,7 +229,6 @@ impl AsmOptions {
|
||||||
pub struct AsmRegOperand {
|
pub struct AsmRegOperand {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
}
|
}
|
||||||
impl ast::HasName for AsmRegOperand {}
|
|
||||||
impl AsmRegOperand {
|
impl AsmRegOperand {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn asm_dir_spec(&self) -> Option<AsmDirSpec> { support::child(&self.syntax) }
|
pub fn asm_dir_spec(&self) -> Option<AsmDirSpec> { support::child(&self.syntax) }
|
||||||
|
@ -229,8 +240,6 @@ impl AsmRegOperand {
|
||||||
pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
|
pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
|
pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
|
||||||
#[inline]
|
|
||||||
pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -2224,14 +2233,19 @@ impl ast::HasVisibility for Adt {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum AsmOperand {
|
pub enum AsmOperand {
|
||||||
AsmClobberAbi(AsmClobberAbi),
|
|
||||||
AsmConst(AsmConst),
|
AsmConst(AsmConst),
|
||||||
AsmLabel(AsmLabel),
|
AsmLabel(AsmLabel),
|
||||||
AsmOptions(AsmOptions),
|
|
||||||
AsmRegOperand(AsmRegOperand),
|
AsmRegOperand(AsmRegOperand),
|
||||||
AsmSym(AsmSym),
|
AsmSym(AsmSym),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum AsmPiece {
|
||||||
|
AsmClobberAbi(AsmClobberAbi),
|
||||||
|
AsmOperandNamed(AsmOperandNamed),
|
||||||
|
AsmOptions(AsmOptions),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum AssocItem {
|
pub enum AssocItem {
|
||||||
Const(Const),
|
Const(Const),
|
||||||
|
@ -2581,6 +2595,20 @@ impl AstNode for AsmOperandExpr {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
|
impl AstNode for AsmOperandNamed {
|
||||||
|
#[inline]
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPERAND_NAMED }
|
||||||
|
#[inline]
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
if Self::can_cast(syntax.kind()) {
|
||||||
|
Some(Self { syntax })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
|
}
|
||||||
impl AstNode for AsmOption {
|
impl AstNode for AsmOption {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTION }
|
fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTION }
|
||||||
|
@ -4589,10 +4617,6 @@ impl AstNode for Adt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<AsmClobberAbi> for AsmOperand {
|
|
||||||
#[inline]
|
|
||||||
fn from(node: AsmClobberAbi) -> AsmOperand { AsmOperand::AsmClobberAbi(node) }
|
|
||||||
}
|
|
||||||
impl From<AsmConst> for AsmOperand {
|
impl From<AsmConst> for AsmOperand {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(node: AsmConst) -> AsmOperand { AsmOperand::AsmConst(node) }
|
fn from(node: AsmConst) -> AsmOperand { AsmOperand::AsmConst(node) }
|
||||||
|
@ -4601,10 +4625,6 @@ impl From<AsmLabel> for AsmOperand {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(node: AsmLabel) -> AsmOperand { AsmOperand::AsmLabel(node) }
|
fn from(node: AsmLabel) -> AsmOperand { AsmOperand::AsmLabel(node) }
|
||||||
}
|
}
|
||||||
impl From<AsmOptions> for AsmOperand {
|
|
||||||
#[inline]
|
|
||||||
fn from(node: AsmOptions) -> AsmOperand { AsmOperand::AsmOptions(node) }
|
|
||||||
}
|
|
||||||
impl From<AsmRegOperand> for AsmOperand {
|
impl From<AsmRegOperand> for AsmOperand {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(node: AsmRegOperand) -> AsmOperand { AsmOperand::AsmRegOperand(node) }
|
fn from(node: AsmRegOperand) -> AsmOperand { AsmOperand::AsmRegOperand(node) }
|
||||||
|
@ -4616,18 +4636,13 @@ impl From<AsmSym> for AsmOperand {
|
||||||
impl AstNode for AsmOperand {
|
impl AstNode for AsmOperand {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn can_cast(kind: SyntaxKind) -> bool {
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
matches!(
|
matches!(kind, ASM_CONST | ASM_LABEL | ASM_REG_OPERAND | ASM_SYM)
|
||||||
kind,
|
|
||||||
ASM_CLOBBER_ABI | ASM_CONST | ASM_LABEL | ASM_OPTIONS | ASM_REG_OPERAND | ASM_SYM
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
let res = match syntax.kind() {
|
let res = match syntax.kind() {
|
||||||
ASM_CLOBBER_ABI => AsmOperand::AsmClobberAbi(AsmClobberAbi { syntax }),
|
|
||||||
ASM_CONST => AsmOperand::AsmConst(AsmConst { syntax }),
|
ASM_CONST => AsmOperand::AsmConst(AsmConst { syntax }),
|
||||||
ASM_LABEL => AsmOperand::AsmLabel(AsmLabel { syntax }),
|
ASM_LABEL => AsmOperand::AsmLabel(AsmLabel { syntax }),
|
||||||
ASM_OPTIONS => AsmOperand::AsmOptions(AsmOptions { syntax }),
|
|
||||||
ASM_REG_OPERAND => AsmOperand::AsmRegOperand(AsmRegOperand { syntax }),
|
ASM_REG_OPERAND => AsmOperand::AsmRegOperand(AsmRegOperand { syntax }),
|
||||||
ASM_SYM => AsmOperand::AsmSym(AsmSym { syntax }),
|
ASM_SYM => AsmOperand::AsmSym(AsmSym { syntax }),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
|
@ -4637,15 +4652,49 @@ impl AstNode for AsmOperand {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn syntax(&self) -> &SyntaxNode {
|
fn syntax(&self) -> &SyntaxNode {
|
||||||
match self {
|
match self {
|
||||||
AsmOperand::AsmClobberAbi(it) => &it.syntax,
|
|
||||||
AsmOperand::AsmConst(it) => &it.syntax,
|
AsmOperand::AsmConst(it) => &it.syntax,
|
||||||
AsmOperand::AsmLabel(it) => &it.syntax,
|
AsmOperand::AsmLabel(it) => &it.syntax,
|
||||||
AsmOperand::AsmOptions(it) => &it.syntax,
|
|
||||||
AsmOperand::AsmRegOperand(it) => &it.syntax,
|
AsmOperand::AsmRegOperand(it) => &it.syntax,
|
||||||
AsmOperand::AsmSym(it) => &it.syntax,
|
AsmOperand::AsmSym(it) => &it.syntax,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl From<AsmClobberAbi> for AsmPiece {
|
||||||
|
#[inline]
|
||||||
|
fn from(node: AsmClobberAbi) -> AsmPiece { AsmPiece::AsmClobberAbi(node) }
|
||||||
|
}
|
||||||
|
impl From<AsmOperandNamed> for AsmPiece {
|
||||||
|
#[inline]
|
||||||
|
fn from(node: AsmOperandNamed) -> AsmPiece { AsmPiece::AsmOperandNamed(node) }
|
||||||
|
}
|
||||||
|
impl From<AsmOptions> for AsmPiece {
|
||||||
|
#[inline]
|
||||||
|
fn from(node: AsmOptions) -> AsmPiece { AsmPiece::AsmOptions(node) }
|
||||||
|
}
|
||||||
|
impl AstNode for AsmPiece {
|
||||||
|
#[inline]
|
||||||
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
|
matches!(kind, ASM_CLOBBER_ABI | ASM_OPERAND_NAMED | ASM_OPTIONS)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||||
|
let res = match syntax.kind() {
|
||||||
|
ASM_CLOBBER_ABI => AsmPiece::AsmClobberAbi(AsmClobberAbi { syntax }),
|
||||||
|
ASM_OPERAND_NAMED => AsmPiece::AsmOperandNamed(AsmOperandNamed { syntax }),
|
||||||
|
ASM_OPTIONS => AsmPiece::AsmOptions(AsmOptions { syntax }),
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn syntax(&self) -> &SyntaxNode {
|
||||||
|
match self {
|
||||||
|
AsmPiece::AsmClobberAbi(it) => &it.syntax,
|
||||||
|
AsmPiece::AsmOperandNamed(it) => &it.syntax,
|
||||||
|
AsmPiece::AsmOptions(it) => &it.syntax,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<Const> for AssocItem {
|
impl From<Const> for AssocItem {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
|
fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
|
||||||
|
@ -6181,7 +6230,7 @@ impl AstNode for AnyHasName {
|
||||||
fn can_cast(kind: SyntaxKind) -> bool {
|
fn can_cast(kind: SyntaxKind) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
kind,
|
kind,
|
||||||
ASM_REG_OPERAND
|
ASM_OPERAND_NAMED
|
||||||
| CONST
|
| CONST
|
||||||
| CONST_PARAM
|
| CONST_PARAM
|
||||||
| ENUM
|
| ENUM
|
||||||
|
@ -6211,9 +6260,9 @@ impl AstNode for AnyHasName {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||||
}
|
}
|
||||||
impl From<AsmRegOperand> for AnyHasName {
|
impl From<AsmOperandNamed> for AnyHasName {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(node: AsmRegOperand) -> AnyHasName { AnyHasName { syntax: node.syntax } }
|
fn from(node: AsmOperandNamed) -> AnyHasName { AnyHasName { syntax: node.syntax } }
|
||||||
}
|
}
|
||||||
impl From<Const> for AnyHasName {
|
impl From<Const> for AnyHasName {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -6460,6 +6509,11 @@ impl std::fmt::Display for AsmOperand {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for AsmPiece {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::fmt::Display for AssocItem {
|
impl std::fmt::Display for AssocItem {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
@ -6560,6 +6614,11 @@ impl std::fmt::Display for AsmOperandExpr {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl std::fmt::Display for AsmOperandNamed {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl std::fmt::Display for AsmOption {
|
impl std::fmt::Display for AsmOption {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Display::fmt(self.syntax(), f)
|
std::fmt::Display::fmt(self.syntax(), f)
|
||||||
|
|
Loading…
Reference in a new issue