@@ -36,37 +36,74 @@ pub struct AsmArgs {
3636/// - `Ok(true)` if the current token matches the keyword, and was expected
3737/// - `Ok(false)` if the current token does not match the keyword
3838/// - `Err(_)` if the current token matches the keyword, but was not expected
39- fn eat_operand_keyword < ' a > ( p : & mut Parser < ' a > , symbol : Symbol , expect : bool ) -> PResult < ' a , bool > {
40- if expect {
39+ fn eat_operand_keyword < ' a > (
40+ p : & mut Parser < ' a > ,
41+ symbol : Symbol ,
42+ asm_macro : AsmMacro ,
43+ ) -> PResult < ' a , bool > {
44+ if matches ! ( asm_macro, AsmMacro :: Asm ) {
4145 Ok ( p. eat_keyword ( symbol) )
4246 } else {
4347 let span = p. token . span ;
4448 if p. eat_keyword_noexpect ( symbol) {
4549 // in gets printed as `r#in` otherwise
4650 let symbol = if symbol == kw:: In { "in" } else { symbol. as_str ( ) } ;
47- Err ( p. dcx ( ) . create_err ( errors:: GlobalAsmUnsupportedOperand { span, symbol } ) )
51+ Err ( p. dcx ( ) . create_err ( errors:: AsmUnsupportedOperand {
52+ span,
53+ symbol,
54+ macro_name : asm_macro. macro_name ( ) ,
55+ } ) )
4856 } else {
4957 Ok ( false )
5058 }
5159 }
5260}
5361
62+ // Public for rustfmt consumption.
63+ #[ derive( Copy , Clone ) ]
64+ pub enum AsmMacro {
65+ /// The `asm!` macro
66+ Asm ,
67+ /// The `global_asm!` macro
68+ GlobalAsm ,
69+ /// The `naked_asm!` macro
70+ NakedAsm ,
71+ }
72+
73+ impl AsmMacro {
74+ const fn macro_name ( & self ) -> & ' static str {
75+ match self {
76+ AsmMacro :: Asm => "asm" ,
77+ AsmMacro :: GlobalAsm => "global_asm" ,
78+ AsmMacro :: NakedAsm => "naked_asm" ,
79+ }
80+ }
81+
82+ const fn is_supported_option ( & self , option : ast:: InlineAsmOptions ) -> bool {
83+ match self {
84+ AsmMacro :: Asm => true ,
85+ AsmMacro :: GlobalAsm => ast:: InlineAsmOptions :: GLOBAL_OPTIONS . contains ( option) ,
86+ AsmMacro :: NakedAsm => ast:: InlineAsmOptions :: NAKED_OPTIONS . contains ( option) ,
87+ }
88+ }
89+ }
90+
5491fn parse_args < ' a > (
5592 ecx : & ExtCtxt < ' a > ,
5693 sp : Span ,
5794 tts : TokenStream ,
58- is_global_asm : bool ,
95+ asm_macro : AsmMacro ,
5996) -> PResult < ' a , AsmArgs > {
6097 let mut p = ecx. new_parser_from_tts ( tts) ;
61- parse_asm_args ( & mut p, sp, is_global_asm )
98+ parse_asm_args ( & mut p, sp, asm_macro )
6299}
63100
64101// Primarily public for rustfmt consumption.
65102// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
66103pub fn parse_asm_args < ' a > (
67104 p : & mut Parser < ' a > ,
68105 sp : Span ,
69- is_global_asm : bool ,
106+ asm_macro : AsmMacro ,
70107) -> PResult < ' a , AsmArgs > {
71108 let dcx = p. dcx ( ) ;
72109
@@ -109,7 +146,7 @@ pub fn parse_asm_args<'a>(
109146
110147 // Parse options
111148 if p. eat_keyword ( sym:: options) {
112- parse_options ( p, & mut args, is_global_asm ) ?;
149+ parse_options ( p, & mut args, asm_macro ) ?;
113150 allow_templates = false ;
114151 continue ;
115152 }
@@ -128,23 +165,23 @@ pub fn parse_asm_args<'a>(
128165 } ;
129166
130167 let mut explicit_reg = false ;
131- let op = if eat_operand_keyword ( p, kw:: In , !is_global_asm ) ? {
168+ let op = if eat_operand_keyword ( p, kw:: In , asm_macro ) ? {
132169 let reg = parse_reg ( p, & mut explicit_reg) ?;
133170 if p. eat_keyword ( kw:: Underscore ) {
134171 let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
135172 return Err ( err) ;
136173 }
137174 let expr = p. parse_expr ( ) ?;
138175 ast:: InlineAsmOperand :: In { reg, expr }
139- } else if eat_operand_keyword ( p, sym:: out, !is_global_asm ) ? {
176+ } else if eat_operand_keyword ( p, sym:: out, asm_macro ) ? {
140177 let reg = parse_reg ( p, & mut explicit_reg) ?;
141178 let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
142179 ast:: InlineAsmOperand :: Out { reg, expr, late : false }
143- } else if eat_operand_keyword ( p, sym:: lateout, !is_global_asm ) ? {
180+ } else if eat_operand_keyword ( p, sym:: lateout, asm_macro ) ? {
144181 let reg = parse_reg ( p, & mut explicit_reg) ?;
145182 let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
146183 ast:: InlineAsmOperand :: Out { reg, expr, late : true }
147- } else if eat_operand_keyword ( p, sym:: inout, !is_global_asm ) ? {
184+ } else if eat_operand_keyword ( p, sym:: inout, asm_macro ) ? {
148185 let reg = parse_reg ( p, & mut explicit_reg) ?;
149186 if p. eat_keyword ( kw:: Underscore ) {
150187 let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
@@ -158,7 +195,7 @@ pub fn parse_asm_args<'a>(
158195 } else {
159196 ast:: InlineAsmOperand :: InOut { reg, expr, late : false }
160197 }
161- } else if eat_operand_keyword ( p, sym:: inlateout, !is_global_asm ) ? {
198+ } else if eat_operand_keyword ( p, sym:: inlateout, asm_macro ) ? {
162199 let reg = parse_reg ( p, & mut explicit_reg) ?;
163200 if p. eat_keyword ( kw:: Underscore ) {
164201 let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
@@ -172,7 +209,7 @@ pub fn parse_asm_args<'a>(
172209 } else {
173210 ast:: InlineAsmOperand :: InOut { reg, expr, late : true }
174211 }
175- } else if eat_operand_keyword ( p, sym:: label, !is_global_asm ) ? {
212+ } else if eat_operand_keyword ( p, sym:: label, asm_macro ) ? {
176213 let block = p. parse_block ( ) ?;
177214 ast:: InlineAsmOperand :: Label { block }
178215 } else if p. eat_keyword ( kw:: Const ) {
@@ -204,7 +241,7 @@ pub fn parse_asm_args<'a>(
204241 _ => {
205242 let err = dcx. create_err ( errors:: AsmExpectedOther {
206243 span : template. span ,
207- is_global_asm ,
244+ is_inline_asm : matches ! ( asm_macro , AsmMacro :: Asm ) ,
208245 } ) ;
209246 return Err ( err) ;
210247 }
@@ -302,20 +339,25 @@ pub fn parse_asm_args<'a>(
302339 dcx. emit_err ( errors:: AsmMayUnwind { labels_sp } ) ;
303340 }
304341
305- if args. clobber_abis . len ( ) > 0 {
306- if is_global_asm {
307- let err = dcx. create_err ( errors:: GlobalAsmClobberAbi {
308- spans : args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect ( ) ,
309- } ) ;
342+ if !args. clobber_abis . is_empty ( ) {
343+ match asm_macro {
344+ AsmMacro :: GlobalAsm | AsmMacro :: NakedAsm => {
345+ let err = dcx. create_err ( errors:: AsmUnsupportedClobberAbi {
346+ spans : args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect ( ) ,
347+ macro_name : asm_macro. macro_name ( ) ,
348+ } ) ;
310349
311- // Bail out now since this is likely to confuse later stages
312- return Err ( err) ;
313- }
314- if !regclass_outputs. is_empty ( ) {
315- dcx. emit_err ( errors:: AsmClobberNoReg {
316- spans : regclass_outputs,
317- clobbers : args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect ( ) ,
318- } ) ;
350+ // Bail out now since this is likely to confuse later stages
351+ return Err ( err) ;
352+ }
353+ AsmMacro :: Asm => {
354+ if !regclass_outputs. is_empty ( ) {
355+ dcx. emit_err ( errors:: AsmClobberNoReg {
356+ spans : regclass_outputs,
357+ clobbers : args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect ( ) ,
358+ } ) ;
359+ }
360+ }
319361 }
320362 }
321363
@@ -336,10 +378,15 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
336378///
337379/// This function must be called immediately after the option token is parsed.
338380/// Otherwise, the suggestion will be incorrect.
339- fn err_unsupported_option ( p : & Parser < ' _ > , symbol : Symbol , span : Span ) {
381+ fn err_unsupported_option ( p : & Parser < ' _ > , asm_macro : AsmMacro , symbol : Symbol , span : Span ) {
340382 // Tool-only output
341383 let full_span = if p. token == token:: Comma { span. to ( p. token . span ) } else { span } ;
342- p. dcx ( ) . emit_err ( errors:: GlobalAsmUnsupportedOption { span, symbol, full_span } ) ;
384+ p. dcx ( ) . emit_err ( errors:: AsmUnsupportedOption {
385+ span,
386+ symbol,
387+ full_span,
388+ macro_name : asm_macro. macro_name ( ) ,
389+ } ) ;
343390}
344391
345392/// Try to set the provided option in the provided `AsmArgs`.
@@ -350,12 +397,12 @@ fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
350397fn try_set_option < ' a > (
351398 p : & Parser < ' a > ,
352399 args : & mut AsmArgs ,
353- is_global_asm : bool ,
400+ asm_macro : AsmMacro ,
354401 symbol : Symbol ,
355402 option : ast:: InlineAsmOptions ,
356403) {
357- if is_global_asm && !ast :: InlineAsmOptions :: GLOBAL_OPTIONS . contains ( option) {
358- err_unsupported_option ( p, symbol, p. prev_token . span ) ;
404+ if !asm_macro . is_supported_option ( option) {
405+ err_unsupported_option ( p, asm_macro , symbol, p. prev_token . span ) ;
359406 } else if args. options . contains ( option) {
360407 err_duplicate_option ( p, symbol, p. prev_token . span ) ;
361408 } else {
@@ -366,7 +413,7 @@ fn try_set_option<'a>(
366413fn parse_options < ' a > (
367414 p : & mut Parser < ' a > ,
368415 args : & mut AsmArgs ,
369- is_global_asm : bool ,
416+ asm_macro : AsmMacro ,
370417) -> PResult < ' a , ( ) > {
371418 let span_start = p. prev_token . span ;
372419
@@ -387,15 +434,14 @@ fn parse_options<'a>(
387434
388435 ' blk: {
389436 for ( symbol, option) in OPTIONS {
390- let kw_matched =
391- if !is_global_asm || ast:: InlineAsmOptions :: GLOBAL_OPTIONS . contains ( option) {
392- p. eat_keyword ( symbol)
393- } else {
394- p. eat_keyword_noexpect ( symbol)
395- } ;
437+ let kw_matched = if asm_macro. is_supported_option ( option) {
438+ p. eat_keyword ( symbol)
439+ } else {
440+ p. eat_keyword_noexpect ( symbol)
441+ } ;
396442
397443 if kw_matched {
398- try_set_option ( p, args, is_global_asm , symbol, option) ;
444+ try_set_option ( p, args, asm_macro , symbol, option) ;
399445 break ' blk;
400446 }
401447 }
@@ -788,7 +834,7 @@ pub(super) fn expand_asm<'cx>(
788834 sp : Span ,
789835 tts : TokenStream ,
790836) -> MacroExpanderResult < ' cx > {
791- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, false ) {
837+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: Asm ) {
792838 Ok ( args) => {
793839 let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, args) else {
794840 return ExpandResult :: Retry ( ( ) ) ;
@@ -817,7 +863,7 @@ pub(super) fn expand_global_asm<'cx>(
817863 sp : Span ,
818864 tts : TokenStream ,
819865) -> MacroExpanderResult < ' cx > {
820- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, true ) {
866+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: GlobalAsm ) {
821867 Ok ( args) => {
822868 let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, args) else {
823869 return ExpandResult :: Retry ( ( ) ) ;
@@ -845,3 +891,32 @@ pub(super) fn expand_global_asm<'cx>(
845891 }
846892 } )
847893}
894+
895+ pub ( super ) fn expand_naked_asm < ' cx > (
896+ ecx : & ' cx mut ExtCtxt < ' _ > ,
897+ sp : Span ,
898+ tts : TokenStream ,
899+ ) -> MacroExpanderResult < ' cx > {
900+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: NakedAsm ) {
901+ Ok ( args) => {
902+ let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, args) else {
903+ return ExpandResult :: Retry ( ( ) ) ;
904+ } ;
905+ let expr = match mac {
906+ Ok ( inline_asm) => P ( ast:: Expr {
907+ id : ast:: DUMMY_NODE_ID ,
908+ kind : ast:: ExprKind :: InlineAsm ( P ( inline_asm) ) ,
909+ span : sp,
910+ attrs : ast:: AttrVec :: new ( ) ,
911+ tokens : None ,
912+ } ) ,
913+ Err ( guar) => DummyResult :: raw_expr ( sp, Some ( guar) ) ,
914+ } ;
915+ MacEager :: expr ( expr)
916+ }
917+ Err ( err) => {
918+ let guar = err. emit ( ) ;
919+ DummyResult :: any ( sp, guar)
920+ }
921+ } )
922+ }
0 commit comments