Skip to content

Commit 124c748

Browse files
committed
Auto merge of #18053 - Veykril:asm-parse, r=Veykril
fix: Couple asm! parsing and lowering fixes
2 parents d927daf + 5b79d92 commit 124c748

File tree

11 files changed

+112
-18
lines changed

11 files changed

+112
-18
lines changed

crates/hir-def/src/body.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub struct BodySourceMap {
105105
// format_args!
106106
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
107107
// asm!
108-
FxHashMap<ExprId, Vec<(syntax::TextRange, usize)>>,
108+
FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>,
109109
)>,
110110
>,
111111

@@ -439,7 +439,7 @@ impl BodySourceMap {
439439
pub fn asm_template_args(
440440
&self,
441441
node: InFile<&ast::AsmExpr>,
442-
) -> Option<(ExprId, &[(syntax::TextRange, usize)])> {
442+
) -> Option<(ExprId, &[Vec<(syntax::TextRange, usize)>])> {
443443
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
444444
let expr = self.expr_map.get(&src)?;
445445
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
@@ -487,7 +487,7 @@ impl BodySourceMap {
487487
&self,
488488
) -> Option<&(
489489
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
490-
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, usize)>>,
490+
FxHashMap<Idx<Expr>, Vec<Vec<(tt::TextRange, usize)>>>,
491491
)> {
492492
self.template_map.as_deref()
493493
}

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,14 @@ impl ExprCollector<'_> {
158158
if !options.contains(AsmOptions::RAW) {
159159
// Don't treat raw asm as a format string.
160160
asm.template()
161-
.filter_map(|it| Some((it.clone(), self.expand_macros_to_string(it)?)))
162-
.for_each(|(expr, (s, is_direct_literal))| {
161+
.enumerate()
162+
.filter_map(|(idx, it)| Some((idx, it.clone(), self.expand_macros_to_string(it)?)))
163+
.for_each(|(idx, expr, (s, is_direct_literal))| {
164+
mappings.resize_with(idx + 1, Vec::default);
163165
let Ok(text) = s.value() else {
164166
return;
165167
};
168+
let mappings = &mut mappings[idx];
166169
let template_snippet = match expr {
167170
ast::Expr::Literal(literal) => match literal.kind() {
168171
ast::LiteralKind::String(s) => Some(s.text().to_owned()),

crates/hir-ty/src/tests/macros.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,11 @@ fn main() {
14981498
43..44 '1': i32
14991499
58..63 'mut o': i32
15001500
66..67 '0': i32
1501+
!95..104 'thread_id': usize
1502+
!103..107 '&foo': &'? i32
1503+
!104..107 'foo': i32
1504+
!115..120 '&muto': &'? mut i32
1505+
!119..120 'o': i32
15011506
293..294 'o': i32
15021507
308..317 'thread_id': usize
15031508
"#]],

crates/hir/src/semantics.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -572,9 +572,11 @@ impl<'db> SemanticsImpl<'db> {
572572
} else {
573573
let asm = ast::AsmExpr::cast(parent)?;
574574
let source_analyzer = self.analyze_no_infer(asm.syntax())?;
575+
let line = asm.template().position(|it| *it.syntax() == literal)?;
575576
let asm = self.wrap_node_infile(asm);
576577
let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
577578
let res = asm_parts
579+
.get(line)?
578580
.iter()
579581
.map(|&(range, index)| {
580582
(
@@ -629,8 +631,9 @@ impl<'db> SemanticsImpl<'db> {
629631
} else {
630632
let asm = ast::AsmExpr::cast(parent)?;
631633
let source_analyzer = &self.analyze_no_infer(asm.syntax())?;
634+
let line = asm.template().position(|it| *it.syntax() == literal)?;
632635
let asm = self.wrap_node_infile(asm);
633-
source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), offset).map(
636+
source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), line, offset).map(
634637
|(owner, (expr, range, index))| {
635638
(range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
636639
},

crates/hir/src/source_analyzer.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -907,12 +907,14 @@ impl SourceAnalyzer {
907907
pub(crate) fn resolve_offset_in_asm_template(
908908
&self,
909909
asm: InFile<&ast::AsmExpr>,
910+
line: usize,
910911
offset: TextSize,
911912
) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> {
912913
let (def, _, body_source_map) = self.def.as_ref()?;
913914
let (expr, args) = body_source_map.asm_template_args(asm)?;
914915
Some(*def).zip(
915-
args.iter()
916+
args.get(line)?
917+
.iter()
916918
.find(|(range, _)| range.contains_inclusive(offset))
917919
.map(|(range, idx)| (expr, *range, *idx)),
918920
)
@@ -944,7 +946,7 @@ impl SourceAnalyzer {
944946
pub(crate) fn as_asm_parts(
945947
&self,
946948
asm: InFile<&ast::AsmExpr>,
947-
) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> {
949+
) -> Option<(DefWithBodyId, (ExprId, &[Vec<(TextRange, usize)>]))> {
948950
let (def, _, body_source_map) = self.def.as_ref()?;
949951
Some(*def).zip(body_source_map.asm_template_args(asm))
950952
}

crates/ide/src/highlight_related.rs

+30
Original file line numberDiff line numberDiff line change
@@ -2004,6 +2004,36 @@ fn main() {
20042004
{
20052005
return;
20062006
}
2007+
"#,
2008+
)
2009+
}
2010+
2011+
#[test]
2012+
fn asm() {
2013+
check(
2014+
r#"
2015+
//- minicore: asm
2016+
#[inline]
2017+
pub unsafe fn bootstrap() -> ! {
2018+
builtin#asm(
2019+
"blabla",
2020+
"mrs {tmp}, CONTROL",
2021+
// ^^^ read
2022+
"blabla",
2023+
"bics {tmp}, {spsel}",
2024+
// ^^^ read
2025+
"blabla",
2026+
"msr CONTROL, {tmp}",
2027+
// ^^^ read
2028+
"blabla",
2029+
tmp$0 = inout(reg) 0,
2030+
// ^^^
2031+
aaa = in(reg) 2,
2032+
aaa = in(reg) msp,
2033+
aaa = in(reg) rv,
2034+
options(noreturn, nomem, nostack),
2035+
);
2036+
}
20072037
"#,
20082038
)
20092039
}

crates/ide/src/syntax_highlighting/test_data/highlight_asm.html

+24-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@
5050
<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>
5151
<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>
5252
<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>
53-
<span class="string_literal macro">"%input = </span><span class="variable">O</span><span class="string_literal macro">pLoad _ {</span><span class="variable">0</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
53+
<span class="string_literal macro">"%input = OpLoad _ {</span><span class="variable">0</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
5454
<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>
55-
<span class="string_literal macro">"OpStore {</span><span class="variable">1</span><span class="string_literal macro">} %result</span><span class="variable">"</span><span class="comma macro">,</span>
55+
<span class="string_literal macro">"OpStore {</span><span class="variable">1</span><span class="string_literal macro">} %result"</span><span class="comma macro">,</span>
5656
<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>
5757
<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>
5858
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
@@ -94,4 +94,26 @@
9494
<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>
9595
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
9696
<span class="brace">}</span>
97+
<span class="brace">}</span>
98+
<span class="comment">// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274</span>
99+
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">inline</span><span class="attribute_bracket attribute">]</span>
100+
<span class="keyword">pub</span> <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration public unsafe">bootstrap</span><span class="parenthesis">(</span><span class="value_param declaration">msp</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">u32</span><span class="comma">,</span> <span class="value_param declaration">rv</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">!</span> <span class="brace">{</span>
101+
<span class="comment">// Ensure thumb mode is set.</span>
102+
<span class="keyword">let</span> <span class="variable declaration">rv</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="value_param">rv</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
103+
<span class="keyword">let</span> <span class="variable declaration">msp</span> <span class="operator">=</span> <span class="value_param">msp</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="semicolon">;</span>
104+
<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>
105+
<span class="string_literal macro">"mrs {</span><span class="variable">tmp</span><span class="string_literal macro">}, CONTROL"</span><span class="comma macro">,</span>
106+
<span class="string_literal macro">"bics {</span><span class="variable">tmp</span><span class="string_literal macro">}, {</span><span class="variable">spsel</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
107+
<span class="string_literal macro">"msr CONTROL, {</span><span class="variable">tmp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
108+
<span class="string_literal macro">"isb"</span><span class="comma macro">,</span>
109+
<span class="string_literal macro">"msr MSP, {</span><span class="variable">msp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
110+
<span class="string_literal macro">"bx {</span><span class="variable">rv</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
111+
<span class="comment macro">// `out(reg) _` is not permitted in a `noreturn` asm! call,</span>
112+
<span class="comment macro">// so instead use `in(reg) 0` and don't restore it afterwards.</span>
113+
<span class="variable declaration macro">tmp</span> <span class="operator 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="numeric_literal macro">0</span><span class="comma macro">,</span>
114+
<span class="variable declaration macro">spsel</span> <span class="operator 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="numeric_literal macro">2</span><span class="comma macro">,</span>
115+
<span class="variable declaration macro">msp</span> <span class="operator 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">msp</span><span class="comma macro">,</span>
116+
<span class="variable declaration macro">rv</span> <span class="operator 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">rv</span><span class="comma macro">,</span>
117+
<span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="comma macro">,</span> <span class="keyword macro">nomem</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
118+
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
97119
<span class="brace">}</span></code></pre>

crates/ide/src/syntax_highlighting/test_data/highlight_strings.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@
167167
<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>
168168
<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>
169169
<span class="string_literal macro">"mov {</span><span class="variable">0</span><span class="string_literal macro">}, {</span><span class="variable">1</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
170-
<span class="string_literal macro">"add {</span><span class="variable">0</span><span class="string_literal macro">}, 5</span><span class="variable">"</span><span class="comma macro">,</span>
170+
<span class="string_literal macro">"add {</span><span class="variable">0</span><span class="string_literal macro">}, 5"</span><span class="comma macro">,</span>
171171
<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>
172172
<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>
173173
<span class="parenthesis macro">)</span><span class="semicolon">;</span>

crates/ide/src/syntax_highlighting/tests.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,28 @@ fn main() {
13311331
);
13321332
}
13331333
}
1334+
// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274
1335+
#[inline]
1336+
pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! {
1337+
// Ensure thumb mode is set.
1338+
let rv = (rv as u32) | 1;
1339+
let msp = msp as u32;
1340+
core::arch::asm!(
1341+
"mrs {tmp}, CONTROL",
1342+
"bics {tmp}, {spsel}",
1343+
"msr CONTROL, {tmp}",
1344+
"isb",
1345+
"msr MSP, {msp}",
1346+
"bx {rv}",
1347+
// `out(reg) _` is not permitted in a `noreturn` asm! call,
1348+
// so instead use `in(reg) 0` and don't restore it afterwards.
1349+
tmp = in(reg) 0,
1350+
spsel = in(reg) 2,
1351+
msp = in(reg) msp,
1352+
rv = in(reg) rv,
1353+
options(noreturn, nomem, nostack),
1354+
);
1355+
}
13341356
"#,
13351357
expect_file!["./test_data/highlight_asm.html"],
13361358
false,

crates/parser/src/grammar/expressions/atom.rs

+5
Original file line numberDiff line numberDiff line change
@@ -361,16 +361,20 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
361361
if p.eat(T![in]) || p.eat_contextual_kw(T![out]) || p.eat_contextual_kw(T![lateout]) {
362362
dir_spec.complete(p, ASM_DIR_SPEC);
363363
parse_reg(p);
364+
let op_expr = p.start();
364365
expr(p);
366+
op_expr.complete(p, ASM_OPERAND_EXPR);
365367
op.complete(p, ASM_REG_OPERAND);
366368
op_n.complete(p, ASM_OPERAND_NAMED);
367369
} else if p.eat_contextual_kw(T![inout]) || p.eat_contextual_kw(T![inlateout]) {
368370
dir_spec.complete(p, ASM_DIR_SPEC);
369371
parse_reg(p);
372+
let op_expr = p.start();
370373
expr(p);
371374
if p.eat(T![=>]) {
372375
expr(p);
373376
}
377+
op_expr.complete(p, ASM_OPERAND_EXPR);
374378
op.complete(p, ASM_REG_OPERAND);
375379
op_n.complete(p, ASM_OPERAND_NAMED);
376380
} else if p.eat_contextual_kw(T![label]) {
@@ -430,6 +434,7 @@ fn parse_options(p: &mut Parser<'_>) {
430434
let m = p.start();
431435
if !OPTIONS.iter().any(|&syntax| p.eat_contextual_kw(syntax)) {
432436
p.err_and_bump("expected asm option");
437+
m.abandon(p);
433438
continue;
434439
}
435440
m.complete(p, ASM_OPTION);

crates/parser/test_data/parser/inline/ok/asm_expr.rast

+9-7
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,12 @@ SOURCE_FILE
5050
IDENT "reg"
5151
R_PAREN ")"
5252
WHITESPACE " "
53-
PATH_EXPR
54-
PATH
55-
PATH_SEGMENT
56-
NAME_REF
57-
IDENT "x"
53+
ASM_OPERAND_EXPR
54+
PATH_EXPR
55+
PATH
56+
PATH_SEGMENT
57+
NAME_REF
58+
IDENT "x"
5859
COMMA ","
5960
WHITESPACE "\n "
6061
ASM_OPERAND_NAMED
@@ -72,8 +73,9 @@ SOURCE_FILE
7273
IDENT "reg"
7374
R_PAREN ")"
7475
WHITESPACE " "
75-
UNDERSCORE_EXPR
76-
UNDERSCORE "_"
76+
ASM_OPERAND_EXPR
77+
UNDERSCORE_EXPR
78+
UNDERSCORE "_"
7779
COMMA ","
7880
WHITESPACE "\n "
7981
R_PAREN ")"

0 commit comments

Comments
 (0)