Skip to content

Commit 811905f

Browse files
committed
Give InlineAsmOperand a HIR representation
1 parent a600e1d commit 811905f

File tree

23 files changed

+409
-217
lines changed

23 files changed

+409
-217
lines changed

crates/hir-def/src/body.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,14 @@ pub struct BodySourceMap {
100100
field_map_back: FxHashMap<ExprId, FieldSource>,
101101
pat_field_map_back: FxHashMap<PatId, PatFieldSource>,
102102

103-
format_args_template_map: FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
103+
template_map: Option<
104+
Box<(
105+
// format_args!
106+
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
107+
// asm!
108+
FxHashMap<ExprId, Vec<(syntax::TextRange, usize)>>,
109+
)>,
110+
>,
104111

105112
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, MacroFileId>,
106113

@@ -426,7 +433,16 @@ impl BodySourceMap {
426433
node: InFile<&ast::FormatArgsExpr>,
427434
) -> Option<&[(syntax::TextRange, Name)]> {
428435
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
429-
self.format_args_template_map.get(self.expr_map.get(&src)?).map(std::ops::Deref::deref)
436+
self.template_map.as_ref()?.0.get(self.expr_map.get(&src)?).map(std::ops::Deref::deref)
437+
}
438+
439+
pub fn asm_template_args(
440+
&self,
441+
node: InFile<&ast::AsmExpr>,
442+
) -> Option<(ExprId, &[(syntax::TextRange, usize)])> {
443+
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
444+
let expr = self.expr_map.get(&src)?;
445+
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
430446
}
431447

432448
/// Get a reference to the body source map's diagnostics.
@@ -446,11 +462,14 @@ impl BodySourceMap {
446462
field_map_back,
447463
pat_field_map_back,
448464
expansions,
449-
format_args_template_map,
465+
template_map,
450466
diagnostics,
451467
binding_definitions,
452468
} = self;
453-
format_args_template_map.shrink_to_fit();
469+
if let Some(template_map) = template_map {
470+
template_map.0.shrink_to_fit();
471+
template_map.1.shrink_to_fit();
472+
}
454473
expr_map.shrink_to_fit();
455474
expr_map_back.shrink_to_fit();
456475
pat_map.shrink_to_fit();

crates/hir-def/src/body/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1847,7 +1847,7 @@ impl ExprCollector<'_> {
18471847
},
18481848
syntax_ptr,
18491849
);
1850-
self.source_map.format_args_template_map.insert(idx, mappings);
1850+
self.source_map.template_map.get_or_insert_with(Default::default).0.insert(idx, mappings);
18511851
idx
18521852
}
18531853

crates/hir-def/src/body/lower/asm.rs

Lines changed: 79 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use hir_expand::name::Name;
21
use intern::Symbol;
32
use rustc_hash::{FxHashMap, FxHashSet};
43
use syntax::{
@@ -25,7 +24,7 @@ impl ExprCollector<'_> {
2524
let mut named_pos: FxHashMap<usize, Symbol> = Default::default();
2625
let mut named_args: FxHashMap<Symbol, usize> = Default::default();
2726
let mut reg_args: FxHashSet<usize> = Default::default();
28-
for operand in asm.asm_operands() {
27+
for piece in asm.asm_pieces() {
2928
let slot = operands.len();
3029
let mut lower_reg = |reg: Option<ast::AsmRegSpec>| {
3130
let reg = reg?;
@@ -39,14 +38,14 @@ impl ExprCollector<'_> {
3938
}
4039
};
4140

42-
let op = match operand {
43-
ast::AsmOperand::AsmClobberAbi(clobber_abi) => {
41+
let op = match piece {
42+
ast::AsmPiece::AsmClobberAbi(clobber_abi) => {
4443
if let Some(abi_name) = clobber_abi.string_token() {
4544
clobber_abis.insert(Symbol::intern(abi_name.text()));
4645
}
4746
continue;
4847
}
49-
ast::AsmOperand::AsmOptions(opt) => {
48+
ast::AsmPiece::AsmOptions(opt) => {
5049
opt.asm_options().for_each(|opt| {
5150
options |= match opt.syntax().first_token().map_or(T![$], |it| it.kind()) {
5251
T![att_syntax] => AsmOptions::ATT_SYNTAX,
@@ -63,71 +62,82 @@ impl ExprCollector<'_> {
6362
});
6463
continue;
6564
}
66-
ast::AsmOperand::AsmRegOperand(op) => {
67-
let Some(dir_spec) = op.asm_dir_spec() else {
68-
continue;
69-
};
70-
let Some(reg) = lower_reg(op.asm_reg_spec()) else {
71-
continue;
72-
};
65+
ast::AsmPiece::AsmOperandNamed(op) => {
7366
if let Some(name) = op.name() {
7467
let sym = Symbol::intern(&name.text());
7568
named_args.insert(sym.clone(), slot);
7669
named_pos.insert(slot, sym);
7770
}
78-
if dir_spec.in_token().is_some() {
79-
let expr = self
80-
.collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr()));
81-
AsmOperand::In { reg, expr }
82-
} else if dir_spec.out_token().is_some() {
83-
let expr = self
84-
.collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr()));
85-
AsmOperand::Out { reg, expr: Some(expr), late: false }
86-
} else if dir_spec.lateout_token().is_some() {
87-
let expr = self
88-
.collect_expr_opt(op.asm_operand_expr().and_then(|it| it.in_expr()));
89-
AsmOperand::Out { reg, expr: Some(expr), late: true }
90-
} else if dir_spec.inout_token().is_some() {
91-
let Some(op_expr) = op.asm_operand_expr() else { continue };
92-
let in_expr = self.collect_expr_opt(op_expr.in_expr());
93-
let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it));
94-
match out_expr {
95-
Some(out_expr) => AsmOperand::SplitInOut {
96-
reg,
97-
in_expr,
98-
out_expr: Some(out_expr),
99-
late: false,
100-
},
101-
None => AsmOperand::InOut { reg, expr: in_expr, late: false },
71+
let Some(op) = op.asm_operand() else { continue };
72+
match op {
73+
ast::AsmOperand::AsmRegOperand(op) => {
74+
let Some(dir_spec) = op.asm_dir_spec() else {
75+
continue;
76+
};
77+
let Some(reg) = lower_reg(op.asm_reg_spec()) else {
78+
continue;
79+
};
80+
if dir_spec.in_token().is_some() {
81+
let expr = self.collect_expr_opt(
82+
op.asm_operand_expr().and_then(|it| it.in_expr()),
83+
);
84+
AsmOperand::In { reg, expr }
85+
} else if dir_spec.out_token().is_some() {
86+
let expr = self.collect_expr_opt(
87+
op.asm_operand_expr().and_then(|it| it.in_expr()),
88+
);
89+
AsmOperand::Out { reg, expr: Some(expr), late: false }
90+
} else if dir_spec.lateout_token().is_some() {
91+
let expr = self.collect_expr_opt(
92+
op.asm_operand_expr().and_then(|it| it.in_expr()),
93+
);
94+
AsmOperand::Out { reg, expr: Some(expr), late: true }
95+
} else if dir_spec.inout_token().is_some() {
96+
let Some(op_expr) = op.asm_operand_expr() else { continue };
97+
let in_expr = self.collect_expr_opt(op_expr.in_expr());
98+
let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it));
99+
match out_expr {
100+
Some(out_expr) => AsmOperand::SplitInOut {
101+
reg,
102+
in_expr,
103+
out_expr: Some(out_expr),
104+
late: false,
105+
},
106+
None => AsmOperand::InOut { reg, expr: in_expr, late: false },
107+
}
108+
} else if dir_spec.inlateout_token().is_some() {
109+
let Some(op_expr) = op.asm_operand_expr() else { continue };
110+
let in_expr = self.collect_expr_opt(op_expr.in_expr());
111+
let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it));
112+
match out_expr {
113+
Some(out_expr) => AsmOperand::SplitInOut {
114+
reg,
115+
in_expr,
116+
out_expr: Some(out_expr),
117+
late: false,
118+
},
119+
None => AsmOperand::InOut { reg, expr: in_expr, late: false },
120+
}
121+
} else {
122+
continue;
123+
}
102124
}
103-
} else if dir_spec.inlateout_token().is_some() {
104-
let Some(op_expr) = op.asm_operand_expr() else { continue };
105-
let in_expr = self.collect_expr_opt(op_expr.in_expr());
106-
let out_expr = op_expr.out_expr().map(|it| self.collect_expr(it));
107-
match out_expr {
108-
Some(out_expr) => AsmOperand::SplitInOut {
109-
reg,
110-
in_expr,
111-
out_expr: Some(out_expr),
112-
late: false,
113-
},
114-
None => AsmOperand::InOut { reg, expr: in_expr, late: false },
125+
ast::AsmOperand::AsmLabel(l) => {
126+
AsmOperand::Label(self.collect_block_opt(l.block_expr()))
127+
}
128+
ast::AsmOperand::AsmConst(c) => {
129+
AsmOperand::Const(self.collect_expr_opt(c.expr()))
130+
}
131+
ast::AsmOperand::AsmSym(s) => {
132+
let Some(path) =
133+
s.path().and_then(|p| self.expander.parse_path(self.db, p))
134+
else {
135+
continue;
136+
};
137+
AsmOperand::Sym(path)
115138
}
116-
} else {
117-
continue;
118139
}
119140
}
120-
ast::AsmOperand::AsmLabel(l) => {
121-
AsmOperand::Label(self.collect_block_opt(l.block_expr()))
122-
}
123-
ast::AsmOperand::AsmConst(c) => AsmOperand::Const(self.collect_expr_opt(c.expr())),
124-
ast::AsmOperand::AsmSym(s) => {
125-
let Some(path) = s.path().and_then(|p| self.expander.parse_path(self.db, p))
126-
else {
127-
continue;
128-
};
129-
AsmOperand::Sym(path)
130-
}
131141
};
132142
operands.push(op);
133143
}
@@ -192,7 +202,7 @@ impl ExprCollector<'_> {
192202
rustc_parse_format::Piece::NextArgument(arg) => {
193203
// let span = arg_spans.next();
194204

195-
let _operand_idx = match arg.position {
205+
let operand_idx = match arg.position {
196206
rustc_parse_format::ArgumentIs(idx)
197207
| rustc_parse_format::ArgumentImplicitlyIs(idx) => {
198208
if idx >= operands.len()
@@ -206,15 +216,15 @@ impl ExprCollector<'_> {
206216
}
207217
rustc_parse_format::ArgumentNamed(name) => {
208218
let name = Symbol::intern(name);
209-
if let Some(position_span) = to_span(arg.position_span) {
210-
mappings.push((
211-
position_span,
212-
Name::new_symbol_root(name.clone()),
213-
));
214-
}
215219
named_args.get(&name).copied()
216220
}
217221
};
222+
223+
if let Some(operand_idx) = operand_idx {
224+
if let Some(position_span) = to_span(arg.position_span) {
225+
mappings.push((position_span, operand_idx));
226+
}
227+
}
218228
}
219229
}
220230
}
@@ -224,7 +234,7 @@ impl ExprCollector<'_> {
224234
Expr::InlineAsm(InlineAsm { operands: operands.into_boxed_slice(), options }),
225235
syntax_ptr,
226236
);
227-
self.source_map.format_args_template_map.insert(idx, mappings);
237+
self.source_map.template_map.get_or_insert_with(Default::default).1.insert(idx, mappings);
228238
idx
229239
}
230240
}

crates/hir/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use hir_def::{
4343
body::{BodyDiagnostic, SyntheticSyntax},
4444
data::adt::VariantData,
4545
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
46-
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
46+
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
4747
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
4848
lang_item::LangItemTarget,
4949
layout::{self, ReprOptions, TargetDataLayout},
@@ -5246,6 +5246,13 @@ impl Type {
52465246
}
52475247
}
52485248

5249+
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
5250+
pub struct InlineAsmOperand {
5251+
owner: DefWithBodyId,
5252+
expr: ExprId,
5253+
index: usize,
5254+
}
5255+
52495256
// FIXME: Document this
52505257
#[derive(Debug)]
52515258
pub struct Callable {

0 commit comments

Comments
 (0)