@@ -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- fn eat_operand_keyword < ' a > ( p : & mut Parser < ' a > , symbol : Symbol , expect : bool ) -> PResult < ' a , bool > {
41- if expect {
40+ fn eat_operand_keyword < ' a > (
41+ p : & mut Parser < ' a > ,
42+ symbol : Symbol ,
43+ asm_macro : AsmMacro ,
44+ ) -> PResult < ' a , bool > {
45+ if matches ! ( 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+ pub enum AsmMacro {
66+ /// The `asm!` macro
67+ Asm ,
68+ /// The `global_asm!` macro
69+ GlobalAsm ,
70+ /// The `naked_asm!` macro
71+ NakedAsm ,
72+ }
73+
74+ impl AsmMacro {
75+ const fn macro_name ( & self ) -> & ' static str {
76+ match self {
77+ AsmMacro :: Asm => "asm" ,
78+ AsmMacro :: GlobalAsm => "global_asm" ,
79+ AsmMacro :: NakedAsm => "naked_asm" ,
80+ }
81+ }
82+
83+ const fn is_supported_option ( & self , option : ast:: InlineAsmOptions ) -> bool {
84+ match self {
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+
5592fn parse_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 let mut 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`
67104pub fn parse_asm_args < ' a > (
68105 p : & mut Parser < ' 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 let mut explicit_reg = false ;
132- let op = if eat_operand_keyword ( p, kw:: In , !is_global_asm ) ? {
169+ let op = if eat_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 return Err ( err) ;
137174 }
138175 let expr = p. parse_expr ( ) ?;
139176 ast:: InlineAsmOperand :: In { reg, expr }
140- } else if eat_operand_keyword ( p, sym:: out, !is_global_asm ) ? {
177+ } else if eat_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- } else if eat_operand_keyword ( p, sym:: lateout, !is_global_asm ) ? {
181+ } else if eat_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- } else if eat_operand_keyword ( p, sym:: inout, !is_global_asm ) ? {
185+ } else if eat_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- } else if eat_operand_keyword ( p, sym:: inlateout, !is_global_asm ) ? {
199+ } else if eat_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- } else if eat_operand_keyword ( p, sym:: label, !is_global_asm ) ? {
213+ } else if eat_operand_keyword ( p, sym:: label, asm_macro ) ? {
177214 let block = p. parse_block ( ) ?;
178215 ast:: InlineAsmOperand :: Label { block }
179216 } else if 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 return Err ( 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- return Err ( 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+ return Err ( 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- fn err_unsupported_option ( p : & Parser < ' _ > , symbol : Symbol , span : Span ) {
380+ fn err_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) {
349396fn try_set_option < ' a > (
350397 p : & Parser < ' a > ,
351398 args : & mut AsmArgs ,
352- is_global_asm : bool ,
399+ asm_macro : AsmMacro ,
353400 symbol : Symbol ,
354401 option : ast:: InlineAsmOptions ,
355402) {
356- if is_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 } else if 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>(
365412fn parse_options < ' a > (
366413 p : & mut Parser < ' a > ,
367414 args : & mut AsmArgs ,
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) in OPTIONS {
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 ( match parse_args ( ecx, sp, tts, false ) {
846+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: Asm ) {
801847 Ok ( args) => {
802848 let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: Asm , args) else {
803849 return ExpandResult :: Retry ( ( ) ) ;
@@ -865,7 +911,7 @@ pub(super) fn expand_global_asm<'cx>(
865911 sp : Span ,
866912 tts : TokenStream ,
867913) -> MacroExpanderResult < ' cx > {
868- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, true ) {
914+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: GlobalAsm ) {
869915 Ok ( args) => {
870916 let ExpandResult :: 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 ) fn expand_naked_asm < ' cx > (
945+ ecx : & ' cx mut ExtCtxt < ' _ > ,
946+ sp : Span ,
947+ tts : TokenStream ,
948+ ) -> MacroExpanderResult < ' cx > {
949+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: NakedAsm ) {
950+ Ok ( args) => {
951+ let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, args) else {
952+ return ExpandResult :: 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