mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-14 06:15:27 +00:00
asm! parsing and lowering fixes
This commit is contained in:
parent
c075a9980e
commit
f74a0c8801
10 changed files with 106 additions and 18 deletions
|
@ -105,7 +105,7 @@ pub struct BodySourceMap {
|
||||||
// format_args!
|
// format_args!
|
||||||
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
FxHashMap<ExprId, Vec<(syntax::TextRange, Name)>>,
|
||||||
// asm!
|
// asm!
|
||||||
FxHashMap<ExprId, Vec<(syntax::TextRange, usize)>>,
|
FxHashMap<ExprId, Vec<Vec<(syntax::TextRange, usize)>>>,
|
||||||
)>,
|
)>,
|
||||||
>,
|
>,
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ impl BodySourceMap {
|
||||||
pub fn asm_template_args(
|
pub fn asm_template_args(
|
||||||
&self,
|
&self,
|
||||||
node: InFile<&ast::AsmExpr>,
|
node: InFile<&ast::AsmExpr>,
|
||||||
) -> Option<(ExprId, &[(syntax::TextRange, usize)])> {
|
) -> Option<(ExprId, &[Vec<(syntax::TextRange, usize)>])> {
|
||||||
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
let src = node.map(AstPtr::new).map(AstPtr::upcast::<ast::Expr>);
|
||||||
let expr = self.expr_map.get(&src)?;
|
let expr = self.expr_map.get(&src)?;
|
||||||
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
|
Some(*expr).zip(self.template_map.as_ref()?.1.get(expr).map(std::ops::Deref::deref))
|
||||||
|
@ -487,7 +487,7 @@ impl BodySourceMap {
|
||||||
&self,
|
&self,
|
||||||
) -> Option<&(
|
) -> Option<&(
|
||||||
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
|
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, Name)>>,
|
||||||
FxHashMap<Idx<Expr>, Vec<(tt::TextRange, usize)>>,
|
FxHashMap<Idx<Expr>, Vec<Vec<(tt::TextRange, usize)>>>,
|
||||||
)> {
|
)> {
|
||||||
self.template_map.as_deref()
|
self.template_map.as_deref()
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,11 +158,14 @@ impl ExprCollector<'_> {
|
||||||
if !options.contains(AsmOptions::RAW) {
|
if !options.contains(AsmOptions::RAW) {
|
||||||
// Don't treat raw asm as a format string.
|
// Don't treat raw asm as a format string.
|
||||||
asm.template()
|
asm.template()
|
||||||
.filter_map(|it| Some((it.clone(), self.expand_macros_to_string(it)?)))
|
.enumerate()
|
||||||
.for_each(|(expr, (s, is_direct_literal))| {
|
.filter_map(|(idx, it)| Some((idx, it.clone(), self.expand_macros_to_string(it)?)))
|
||||||
|
.for_each(|(idx, expr, (s, is_direct_literal))| {
|
||||||
|
mappings.resize_with(idx + 1, Vec::default);
|
||||||
let Ok(text) = s.value() else {
|
let Ok(text) = s.value() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
let mappings = &mut mappings[idx];
|
||||||
let template_snippet = match expr {
|
let template_snippet = match expr {
|
||||||
ast::Expr::Literal(literal) => match literal.kind() {
|
ast::Expr::Literal(literal) => match literal.kind() {
|
||||||
ast::LiteralKind::String(s) => Some(s.text().to_owned()),
|
ast::LiteralKind::String(s) => Some(s.text().to_owned()),
|
||||||
|
|
|
@ -572,9 +572,11 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
} else {
|
} else {
|
||||||
let asm = ast::AsmExpr::cast(parent)?;
|
let asm = ast::AsmExpr::cast(parent)?;
|
||||||
let source_analyzer = self.analyze_no_infer(asm.syntax())?;
|
let source_analyzer = self.analyze_no_infer(asm.syntax())?;
|
||||||
|
let line = asm.template().position(|it| *it.syntax() == literal)?;
|
||||||
let asm = self.wrap_node_infile(asm);
|
let asm = self.wrap_node_infile(asm);
|
||||||
let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
|
let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
|
||||||
let res = asm_parts
|
let res = asm_parts
|
||||||
|
.get(line)?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(range, index)| {
|
.map(|&(range, index)| {
|
||||||
(
|
(
|
||||||
|
@ -629,8 +631,9 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
} else {
|
} else {
|
||||||
let asm = ast::AsmExpr::cast(parent)?;
|
let asm = ast::AsmExpr::cast(parent)?;
|
||||||
let source_analyzer = &self.analyze_no_infer(asm.syntax())?;
|
let source_analyzer = &self.analyze_no_infer(asm.syntax())?;
|
||||||
|
let line = asm.template().position(|it| *it.syntax() == literal)?;
|
||||||
let asm = self.wrap_node_infile(asm);
|
let asm = self.wrap_node_infile(asm);
|
||||||
source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), offset).map(
|
source_analyzer.resolve_offset_in_asm_template(asm.as_ref(), line, offset).map(
|
||||||
|(owner, (expr, range, index))| {
|
|(owner, (expr, range, index))| {
|
||||||
(range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
|
(range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
|
||||||
},
|
},
|
||||||
|
|
|
@ -907,12 +907,14 @@ impl SourceAnalyzer {
|
||||||
pub(crate) fn resolve_offset_in_asm_template(
|
pub(crate) fn resolve_offset_in_asm_template(
|
||||||
&self,
|
&self,
|
||||||
asm: InFile<&ast::AsmExpr>,
|
asm: InFile<&ast::AsmExpr>,
|
||||||
|
line: usize,
|
||||||
offset: TextSize,
|
offset: TextSize,
|
||||||
) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> {
|
) -> Option<(DefWithBodyId, (ExprId, TextRange, usize))> {
|
||||||
let (def, _, body_source_map) = self.def.as_ref()?;
|
let (def, _, body_source_map) = self.def.as_ref()?;
|
||||||
let (expr, args) = body_source_map.asm_template_args(asm)?;
|
let (expr, args) = body_source_map.asm_template_args(asm)?;
|
||||||
Some(*def).zip(
|
Some(*def).zip(
|
||||||
args.iter()
|
args.get(line)?
|
||||||
|
.iter()
|
||||||
.find(|(range, _)| range.contains_inclusive(offset))
|
.find(|(range, _)| range.contains_inclusive(offset))
|
||||||
.map(|(range, idx)| (expr, *range, *idx)),
|
.map(|(range, idx)| (expr, *range, *idx)),
|
||||||
)
|
)
|
||||||
|
@ -944,7 +946,7 @@ impl SourceAnalyzer {
|
||||||
pub(crate) fn as_asm_parts(
|
pub(crate) fn as_asm_parts(
|
||||||
&self,
|
&self,
|
||||||
asm: InFile<&ast::AsmExpr>,
|
asm: InFile<&ast::AsmExpr>,
|
||||||
) -> Option<(DefWithBodyId, (ExprId, &[(TextRange, usize)]))> {
|
) -> Option<(DefWithBodyId, (ExprId, &[Vec<(TextRange, usize)>]))> {
|
||||||
let (def, _, body_source_map) = self.def.as_ref()?;
|
let (def, _, body_source_map) = self.def.as_ref()?;
|
||||||
Some(*def).zip(body_source_map.asm_template_args(asm))
|
Some(*def).zip(body_source_map.asm_template_args(asm))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2004,6 +2004,36 @@ fn main() {
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn asm() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
//- minicore: asm
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn bootstrap() -> ! {
|
||||||
|
builtin#asm(
|
||||||
|
"blabla",
|
||||||
|
"mrs {tmp}, CONTROL",
|
||||||
|
// ^^^ read
|
||||||
|
"blabla",
|
||||||
|
"bics {tmp}, {spsel}",
|
||||||
|
// ^^^ read
|
||||||
|
"blabla",
|
||||||
|
"msr CONTROL, {tmp}",
|
||||||
|
// ^^^ read
|
||||||
|
"blabla",
|
||||||
|
tmp$0 = inout(reg) 0,
|
||||||
|
// ^^^
|
||||||
|
aaa = in(reg) 2,
|
||||||
|
aaa = in(reg) msp,
|
||||||
|
aaa = in(reg) rv,
|
||||||
|
options(noreturn, nomem, nostack),
|
||||||
|
);
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,9 @@ 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 = </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>
|
<span class="string_literal macro">"%input = OpLoad _ {</span><span class="variable">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 {</span><span class="variable">1</span><span class="string_literal macro">} %result</span><span class="variable">"</span><span class="comma macro">,</span>
|
<span class="string_literal macro">"OpStore {</span><span class="variable">1</span><span class="string_literal macro">} %result"</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>
|
||||||
|
@ -94,4 +94,26 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<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>
|
||||||
|
<span class="brace">}</span>
|
||||||
|
<span class="comment">// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274</span>
|
||||||
|
<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>
|
||||||
|
<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">-></span> <span class="builtin_type">!</span> <span class="brace">{</span>
|
||||||
|
<span class="comment">// Ensure thumb mode is set.</span>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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">"mrs {</span><span class="variable">tmp</span><span class="string_literal macro">}, CONTROL"</span><span class="comma macro">,</span>
|
||||||
|
<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>
|
||||||
|
<span class="string_literal macro">"msr CONTROL, {</span><span class="variable">tmp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||||
|
<span class="string_literal macro">"isb"</span><span class="comma macro">,</span>
|
||||||
|
<span class="string_literal macro">"msr MSP, {</span><span class="variable">msp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||||
|
<span class="string_literal macro">"bx {</span><span class="variable">rv</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
|
||||||
|
<span class="comment macro">// `out(reg) _` is not permitted in a `noreturn` asm! call,</span>
|
||||||
|
<span class="comment macro">// so instead use `in(reg) 0` and don't restore it afterwards.</span>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="brace">}</span></code></pre>
|
<span class="brace">}</span></code></pre>
|
|
@ -167,7 +167,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<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 {</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>
|
<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>
|
||||||
<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>
|
<span class="string_literal macro">"add {</span><span class="variable">0</span><span class="string_literal macro">}, 5"</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>
|
||||||
|
|
|
@ -1331,6 +1331,28 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! {
|
||||||
|
// Ensure thumb mode is set.
|
||||||
|
let rv = (rv as u32) | 1;
|
||||||
|
let msp = msp as u32;
|
||||||
|
core::arch::asm!(
|
||||||
|
"mrs {tmp}, CONTROL",
|
||||||
|
"bics {tmp}, {spsel}",
|
||||||
|
"msr CONTROL, {tmp}",
|
||||||
|
"isb",
|
||||||
|
"msr MSP, {msp}",
|
||||||
|
"bx {rv}",
|
||||||
|
// `out(reg) _` is not permitted in a `noreturn` asm! call,
|
||||||
|
// so instead use `in(reg) 0` and don't restore it afterwards.
|
||||||
|
tmp = in(reg) 0,
|
||||||
|
spsel = in(reg) 2,
|
||||||
|
msp = in(reg) msp,
|
||||||
|
rv = in(reg) rv,
|
||||||
|
options(noreturn, nomem, nostack),
|
||||||
|
);
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
expect_file!["./test_data/highlight_asm.html"],
|
expect_file!["./test_data/highlight_asm.html"],
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -361,16 +361,20 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
|
||||||
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);
|
||||||
|
let op_expr = p.start();
|
||||||
expr(p);
|
expr(p);
|
||||||
|
op_expr.complete(p, ASM_OPERAND_EXPR);
|
||||||
op.complete(p, ASM_REG_OPERAND);
|
op.complete(p, ASM_REG_OPERAND);
|
||||||
op_n.complete(p, ASM_OPERAND_NAMED);
|
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);
|
||||||
|
let op_expr = p.start();
|
||||||
expr(p);
|
expr(p);
|
||||||
if p.eat(T![=>]) {
|
if p.eat(T![=>]) {
|
||||||
expr(p);
|
expr(p);
|
||||||
}
|
}
|
||||||
|
op_expr.complete(p, ASM_OPERAND_EXPR);
|
||||||
op.complete(p, ASM_REG_OPERAND);
|
op.complete(p, ASM_REG_OPERAND);
|
||||||
op_n.complete(p, ASM_OPERAND_NAMED);
|
op_n.complete(p, ASM_OPERAND_NAMED);
|
||||||
} else if p.eat_contextual_kw(T![label]) {
|
} else if p.eat_contextual_kw(T![label]) {
|
||||||
|
|
|
@ -50,11 +50,12 @@ SOURCE_FILE
|
||||||
IDENT "reg"
|
IDENT "reg"
|
||||||
R_PAREN ")"
|
R_PAREN ")"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
PATH_EXPR
|
ASM_OPERAND_EXPR
|
||||||
PATH
|
PATH_EXPR
|
||||||
PATH_SEGMENT
|
PATH
|
||||||
NAME_REF
|
PATH_SEGMENT
|
||||||
IDENT "x"
|
NAME_REF
|
||||||
|
IDENT "x"
|
||||||
COMMA ","
|
COMMA ","
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
ASM_OPERAND_NAMED
|
ASM_OPERAND_NAMED
|
||||||
|
@ -72,8 +73,9 @@ SOURCE_FILE
|
||||||
IDENT "reg"
|
IDENT "reg"
|
||||||
R_PAREN ")"
|
R_PAREN ")"
|
||||||
WHITESPACE " "
|
WHITESPACE " "
|
||||||
UNDERSCORE_EXPR
|
ASM_OPERAND_EXPR
|
||||||
UNDERSCORE "_"
|
UNDERSCORE_EXPR
|
||||||
|
UNDERSCORE "_"
|
||||||
COMMA ","
|
COMMA ","
|
||||||
WHITESPACE "\n "
|
WHITESPACE "\n "
|
||||||
R_PAREN ")"
|
R_PAREN ")"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue