Skip to content

Commit aa5bbf0

Browse files
committed
implement naked_asm macro
1 parent 96d9d8a commit aa5bbf0

5 files changed

Lines changed: 160 additions & 68 deletions

File tree

‎compiler/rustc_builtin_macros/messages.ftl‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ builtin_macros_asm_duplicate_arg = duplicate argument named `{$name}`
1212
builtin_macros_asm_expected_comma = expected token: `,`
1313
.label = expected `,`
1414
15-
builtin_macros_asm_expected_other = expected operand, {$is_global_asm->
16-
[true] options
17-
*[false] clobber_abi, options
15+
builtin_macros_asm_expected_other = expected operand, {$is_inline_asm->
16+
[false] options
17+
*[true] clobber_abi, options
1818
}, or additional template string
1919
2020
builtin_macros_asm_expected_string_literal = expected string literal
@@ -51,6 +51,15 @@ builtin_macros_asm_sym_no_path = expected a path for argument to `sym`
5151
5252
builtin_macros_asm_underscore_input = _ cannot be used for input operands
5353
54+
builtin_macros_asm_unsupported_clobber_abi = `clobber_abi` cannot be used with `{$macro_name}!`
55+
56+
builtin_macros_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `{$macro_name}!`
57+
.label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it
58+
59+
builtin_macros_asm_unsupported_option = the `{$symbol}` option cannot be used with `{$macro_name}!`
60+
.label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
61+
.suggestion = remove this option
62+
5463
builtin_macros_assert_missing_comma = unexpected string literal
5564
.suggestion = try adding a comma
5665
@@ -194,15 +203,6 @@ builtin_macros_format_unused_args = multiple unused formatting arguments
194203
195204
builtin_macros_format_use_positional = consider using a positional formatting argument instead
196205
197-
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
198-
199-
builtin_macros_global_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `global_asm!`
200-
.label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it
201-
202-
builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
203-
.label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
204-
.suggestion = remove this option
205-
206206
builtin_macros_invalid_crate_attribute = invalid crate attribute
207207
208208
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes

‎compiler/rustc_builtin_macros/src/asm.rs‎

Lines changed: 117 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -37,37 +37,74 @@ pub struct AsmArgs {
3737
/// - `Ok(true)` if the current token matches the keyword, and was expected
3838
/// - `Ok(false)` if the current token does not match the keyword
3939
/// - `Err(_)` if the current token matches the keyword, but was not expected
40-
fneat_operand_keyword<'a>(p:&mutParser<'a>,symbol:Symbol,expect:bool) -> PResult<'a,bool>{
41-
if expect {
40+
fneat_operand_keyword<'a>(
41+
p:&mutParser<'a>,
42+
symbol:Symbol,
43+
asm_macro:AsmMacro,
44+
) -> PResult<'a,bool>{
45+
ifmatches!(asm_macro,AsmMacro::Asm){
4246
Ok(p.eat_keyword(symbol))
4347
}else{
4448
let span = p.token.span;
4549
if p.eat_keyword_noexpect(symbol){
4650
// in gets printed as `r#in` otherwise
4751
let symbol = if symbol == kw::In{"in"}else{ symbol.as_str()};
48-
Err(p.dcx().create_err(errors::GlobalAsmUnsupportedOperand{ span, symbol }))
52+
Err(p.dcx().create_err(errors::AsmUnsupportedOperand{
53+
span,
54+
symbol,
55+
macro_name: asm_macro.macro_name(),
56+
}))
4957
}else{
5058
Ok(false)
5159
}
5260
}
5361
}
5462

63+
// Public for rustfmt consumption.
64+
#[derive(Copy,Clone)]
65+
pubenumAsmMacro{
66+
/// The `asm!` macro
67+
Asm,
68+
/// The `global_asm!` macro
69+
GlobalAsm,
70+
/// The `naked_asm!` macro
71+
NakedAsm,
72+
}
73+
74+
implAsmMacro{
75+
constfnmacro_name(&self) -> &'staticstr{
76+
matchself{
77+
AsmMacro::Asm => "asm",
78+
AsmMacro::GlobalAsm => "global_asm",
79+
AsmMacro::NakedAsm => "naked_asm",
80+
}
81+
}
82+
83+
constfnis_supported_option(&self,option: ast::InlineAsmOptions) -> bool{
84+
matchself{
85+
AsmMacro::Asm => true,
86+
AsmMacro::GlobalAsm => ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option),
87+
AsmMacro::NakedAsm => ast::InlineAsmOptions::NAKED_OPTIONS.contains(option),
88+
}
89+
}
90+
}
91+
5592
fnparse_args<'a>(
5693
ecx:&ExtCtxt<'a>,
5794
sp:Span,
5895
tts:TokenStream,
59-
is_global_asm:bool,
96+
asm_macro:AsmMacro,
6097
) -> PResult<'a,AsmArgs>{
6198
letmut p = ecx.new_parser_from_tts(tts);
62-
parse_asm_args(&mut p, sp,is_global_asm)
99+
parse_asm_args(&mut p, sp,asm_macro)
63100
}
64101

65102
// Primarily public for rustfmt consumption.
66103
// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
67104
pubfnparse_asm_args<'a>(
68105
p:&mutParser<'a>,
69106
sp:Span,
70-
is_global_asm:bool,
107+
asm_macro:AsmMacro,
71108
) -> PResult<'a,AsmArgs>{
72109
let dcx = p.dcx();
73110

@@ -110,7 +147,7 @@ pub fn parse_asm_args<'a>(
110147

111148
// Parse options
112149
if p.eat_keyword(sym::options){
113-
parse_options(p,&mut args,is_global_asm)?;
150+
parse_options(p,&mut args,asm_macro)?;
114151
allow_templates = false;
115152
continue;
116153
}
@@ -129,23 +166,23 @@ pub fn parse_asm_args<'a>(
129166
};
130167

131168
letmut explicit_reg = false;
132-
let op = ifeat_operand_keyword(p, kw::In,!is_global_asm)? {
169+
let op = ifeat_operand_keyword(p, kw::In,asm_macro)? {
133170
let reg = parse_reg(p,&mut explicit_reg)?;
134171
if p.eat_keyword(kw::Underscore){
135172
let err = dcx.create_err(errors::AsmUnderscoreInput{span: p.token.span});
136173
returnErr(err);
137174
}
138175
let expr = p.parse_expr()?;
139176
ast::InlineAsmOperand::In{ reg, expr }
140-
}elseifeat_operand_keyword(p, sym::out,!is_global_asm)? {
177+
}elseifeat_operand_keyword(p, sym::out,asm_macro)? {
141178
let reg = parse_reg(p,&mut explicit_reg)?;
142179
let expr = if p.eat_keyword(kw::Underscore){None}else{Some(p.parse_expr()?)};
143180
ast::InlineAsmOperand::Out{ reg, expr,late:false}
144-
}elseifeat_operand_keyword(p, sym::lateout,!is_global_asm)? {
181+
}elseifeat_operand_keyword(p, sym::lateout,asm_macro)? {
145182
let reg = parse_reg(p,&mut explicit_reg)?;
146183
let expr = if p.eat_keyword(kw::Underscore){None}else{Some(p.parse_expr()?)};
147184
ast::InlineAsmOperand::Out{ reg, expr,late:true}
148-
}elseifeat_operand_keyword(p, sym::inout,!is_global_asm)? {
185+
}elseifeat_operand_keyword(p, sym::inout,asm_macro)? {
149186
let reg = parse_reg(p,&mut explicit_reg)?;
150187
if p.eat_keyword(kw::Underscore){
151188
let err = dcx.create_err(errors::AsmUnderscoreInput{span: p.token.span});
@@ -159,7 +196,7 @@ pub fn parse_asm_args<'a>(
159196
}else{
160197
ast::InlineAsmOperand::InOut{ reg, expr,late:false}
161198
}
162-
}elseifeat_operand_keyword(p, sym::inlateout,!is_global_asm)? {
199+
}elseifeat_operand_keyword(p, sym::inlateout,asm_macro)? {
163200
let reg = parse_reg(p,&mut explicit_reg)?;
164201
if p.eat_keyword(kw::Underscore){
165202
let err = dcx.create_err(errors::AsmUnderscoreInput{span: p.token.span});
@@ -173,7 +210,7 @@ pub fn parse_asm_args<'a>(
173210
}else{
174211
ast::InlineAsmOperand::InOut{ reg, expr,late:true}
175212
}
176-
}elseifeat_operand_keyword(p, sym::label,!is_global_asm)? {
213+
}elseifeat_operand_keyword(p, sym::label,asm_macro)? {
177214
let block = p.parse_block()?;
178215
ast::InlineAsmOperand::Label{ block }
179216
}elseif p.eat_keyword(kw::Const){
@@ -205,7 +242,7 @@ pub fn parse_asm_args<'a>(
205242
_ => {
206243
let err = dcx.create_err(errors::AsmExpectedOther{
207244
span: template.span,
208-
is_global_asm,
245+
is_inline_asm:matches!(asm_macro,AsmMacro::Asm),
209246
});
210247
returnErr(err);
211248
}
@@ -301,20 +338,25 @@ pub fn parse_asm_args<'a>(
301338
dcx.emit_err(errors::AsmMayUnwind{ labels_sp });
302339
}
303340

304-
if args.clobber_abis.len() > 0{
305-
if is_global_asm {
306-
let err = dcx.create_err(errors::GlobalAsmClobberAbi{
307-
spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
308-
});
341+
if !args.clobber_abis.is_empty(){
342+
match asm_macro {
343+
AsmMacro::GlobalAsm | AsmMacro::NakedAsm => {
344+
let err = dcx.create_err(errors::AsmUnsupportedClobberAbi{
345+
spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
346+
macro_name: asm_macro.macro_name(),
347+
});
309348

310-
// Bail out now since this is likely to confuse later stages
311-
returnErr(err);
312-
}
313-
if !regclass_outputs.is_empty(){
314-
dcx.emit_err(errors::AsmClobberNoReg{
315-
spans: regclass_outputs,
316-
clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
317-
});
349+
// Bail out now since this is likely to confuse later stages
350+
returnErr(err);
351+
}
352+
AsmMacro::Asm => {
353+
if !regclass_outputs.is_empty(){
354+
dcx.emit_err(errors::AsmClobberNoReg{
355+
spans: regclass_outputs,
356+
clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
357+
});
358+
}
359+
}
318360
}
319361
}
320362

@@ -335,10 +377,15 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
335377
///
336378
/// This function must be called immediately after the option token is parsed.
337379
/// Otherwise, the suggestion will be incorrect.
338-
fnerr_unsupported_option(p:&Parser<'_>,symbol:Symbol,span:Span){
380+
fnerr_unsupported_option(p:&Parser<'_>,asm_macro:AsmMacro,symbol:Symbol,span:Span){
339381
// Tool-only output
340382
let full_span = if p.token == token::Comma{ span.to(p.token.span)}else{ span };
341-
p.dcx().emit_err(errors::GlobalAsmUnsupportedOption{ span, symbol, full_span });
383+
p.dcx().emit_err(errors::AsmUnsupportedOption{
384+
span,
385+
symbol,
386+
full_span,
387+
macro_name: asm_macro.macro_name(),
388+
});
342389
}
343390

344391
/// Try to set the provided option in the provided `AsmArgs`.
@@ -349,12 +396,12 @@ fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
349396
fntry_set_option<'a>(
350397
p:&Parser<'a>,
351398
args:&mutAsmArgs,
352-
is_global_asm:bool,
399+
asm_macro:AsmMacro,
353400
symbol:Symbol,
354401
option: ast::InlineAsmOptions,
355402
){
356-
ifis_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option){
357-
err_unsupported_option(p, symbol, p.prev_token.span);
403+
if!asm_macro.is_supported_option(option){
404+
err_unsupported_option(p,asm_macro,symbol, p.prev_token.span);
358405
}elseif args.options.contains(option){
359406
err_duplicate_option(p, symbol, p.prev_token.span);
360407
}else{
@@ -365,7 +412,7 @@ fn try_set_option<'a>(
365412
fnparse_options<'a>(
366413
p:&mutParser<'a>,
367414
args:&mutAsmArgs,
368-
is_global_asm:bool,
415+
asm_macro:AsmMacro,
369416
) -> PResult<'a,()>{
370417
let span_start = p.prev_token.span;
371418

@@ -386,15 +433,14 @@ fn parse_options<'a>(
386433

387434
'blk:{
388435
for(symbol, option)inOPTIONS{
389-
let kw_matched =
390-
if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option){
391-
p.eat_keyword(symbol)
392-
}else{
393-
p.eat_keyword_noexpect(symbol)
394-
};
436+
let kw_matched = if asm_macro.is_supported_option(option){
437+
p.eat_keyword(symbol)
438+
}else{
439+
p.eat_keyword_noexpect(symbol)
440+
};
395441

396442
if kw_matched {
397-
try_set_option(p, args,is_global_asm, symbol, option);
443+
try_set_option(p, args,asm_macro, symbol, option);
398444
break'blk;
399445
}
400446
}
@@ -797,7 +843,7 @@ pub(super) fn expand_asm<'cx>(
797843
sp:Span,
798844
tts:TokenStream,
799845
) -> MacroExpanderResult<'cx>{
800-
ExpandResult::Ready(matchparse_args(ecx, sp, tts,false){
846+
ExpandResult::Ready(matchparse_args(ecx, sp, tts,AsmMacro::Asm){
801847
Ok(args) => {
802848
letExpandResult::Ready(mac) = expand_preparsed_asm(ecx,AsmMacro::Asm, args)else{
803849
returnExpandResult::Retry(());
@@ -865,7 +911,7 @@ pub(super) fn expand_global_asm<'cx>(
865911
sp:Span,
866912
tts:TokenStream,
867913
) -> MacroExpanderResult<'cx>{
868-
ExpandResult::Ready(matchparse_args(ecx, sp, tts,true){
914+
ExpandResult::Ready(matchparse_args(ecx, sp, tts,AsmMacro::GlobalAsm){
869915
Ok(args) => {
870916
letExpandResult::Ready(mac) = expand_preparsed_asm(ecx,AsmMacro::GlobalAsm, args)
871917
else{
@@ -894,3 +940,32 @@ pub(super) fn expand_global_asm<'cx>(
894940
}
895941
})
896942
}
943+
944+
pub(super)fnexpand_naked_asm<'cx>(
945+
ecx:&'cxmutExtCtxt<'_>,
946+
sp:Span,
947+
tts:TokenStream,
948+
) -> MacroExpanderResult<'cx>{
949+
ExpandResult::Ready(matchparse_args(ecx, sp, tts,AsmMacro::NakedAsm){
950+
Ok(args) => {
951+
letExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args)else{
952+
returnExpandResult::Retry(());
953+
};
954+
let expr = match mac {
955+
Ok(inline_asm) => P(ast::Expr{
956+
id: ast::DUMMY_NODE_ID,
957+
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
958+
span: sp,
959+
attrs: ast::AttrVec::new(),
960+
tokens:None,
961+
}),
962+
Err(guar) => DummyResult::raw_expr(sp,Some(guar)),
963+
};
964+
MacEager::expr(expr)
965+
}
966+
Err(err) => {
967+
let guar = err.emit();
968+
DummyResult::any(sp, guar)
969+
}
970+
})
971+
}

0 commit comments

Comments
 (0)