@@ -37,15 +37,23 @@ 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 }
@@ -56,18 +64,18 @@ fn parse_args<'a>(
5664 ecx : & ExtCtxt < ' a > ,
5765 sp : Span ,
5866 tts : TokenStream ,
59- is_global_asm : bool ,
67+ asm_macro : AsmMacro ,
6068) -> PResult < ' a , AsmArgs > {
6169 let mut p = ecx. new_parser_from_tts ( tts) ;
62- parse_asm_args ( & mut p, sp, is_global_asm )
70+ parse_asm_args ( & mut p, sp, asm_macro )
6371}
6472
6573// Primarily public for rustfmt consumption.
6674// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
6775pub fn parse_asm_args < ' a > (
6876 p : & mut Parser < ' a > ,
6977 sp : Span ,
70- is_global_asm : bool ,
78+ asm_macro : AsmMacro ,
7179) -> PResult < ' a , AsmArgs > {
7280 let dcx = p. dcx ( ) ;
7381
@@ -110,7 +118,7 @@ pub fn parse_asm_args<'a>(
110118
111119 // Parse options
112120 if p. eat_keyword ( sym:: options) {
113- parse_options ( p, & mut args, is_global_asm ) ?;
121+ parse_options ( p, & mut args, asm_macro ) ?;
114122 allow_templates = false ;
115123 continue ;
116124 }
@@ -129,23 +137,23 @@ pub fn parse_asm_args<'a>(
129137 } ;
130138
131139 let mut explicit_reg = false ;
132- let op = if eat_operand_keyword ( p, kw:: In , !is_global_asm ) ? {
140+ let op = if eat_operand_keyword ( p, kw:: In , asm_macro ) ? {
133141 let reg = parse_reg ( p, & mut explicit_reg) ?;
134142 if p. eat_keyword ( kw:: Underscore ) {
135143 let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
136144 return Err ( err) ;
137145 }
138146 let expr = p. parse_expr ( ) ?;
139147 ast:: InlineAsmOperand :: In { reg, expr }
140- } else if eat_operand_keyword ( p, sym:: out, !is_global_asm ) ? {
148+ } else if eat_operand_keyword ( p, sym:: out, asm_macro ) ? {
141149 let reg = parse_reg ( p, & mut explicit_reg) ?;
142150 let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
143151 ast:: InlineAsmOperand :: Out { reg, expr, late : false }
144- } else if eat_operand_keyword ( p, sym:: lateout, !is_global_asm ) ? {
152+ } else if eat_operand_keyword ( p, sym:: lateout, asm_macro ) ? {
145153 let reg = parse_reg ( p, & mut explicit_reg) ?;
146154 let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
147155 ast:: InlineAsmOperand :: Out { reg, expr, late : true }
148- } else if eat_operand_keyword ( p, sym:: inout, !is_global_asm ) ? {
156+ } else if eat_operand_keyword ( p, sym:: inout, asm_macro ) ? {
149157 let reg = parse_reg ( p, & mut explicit_reg) ?;
150158 if p. eat_keyword ( kw:: Underscore ) {
151159 let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
@@ -159,7 +167,7 @@ pub fn parse_asm_args<'a>(
159167 } else {
160168 ast:: InlineAsmOperand :: InOut { reg, expr, late : false }
161169 }
162- } else if eat_operand_keyword ( p, sym:: inlateout, !is_global_asm ) ? {
170+ } else if eat_operand_keyword ( p, sym:: inlateout, asm_macro ) ? {
163171 let reg = parse_reg ( p, & mut explicit_reg) ?;
164172 if p. eat_keyword ( kw:: Underscore ) {
165173 let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
@@ -173,7 +181,7 @@ pub fn parse_asm_args<'a>(
173181 } else {
174182 ast:: InlineAsmOperand :: InOut { reg, expr, late : true }
175183 }
176- } else if eat_operand_keyword ( p, sym:: label, !is_global_asm ) ? {
184+ } else if eat_operand_keyword ( p, sym:: label, asm_macro ) ? {
177185 let block = p. parse_block ( ) ?;
178186 ast:: InlineAsmOperand :: Label { block }
179187 } else if p. eat_keyword ( kw:: Const ) {
@@ -205,7 +213,7 @@ pub fn parse_asm_args<'a>(
205213 _ => {
206214 let err = dcx. create_err ( errors:: AsmExpectedOther {
207215 span : template. span ,
208- is_global_asm ,
216+ is_inline_asm : matches ! ( asm_macro , AsmMacro :: Asm ) ,
209217 } ) ;
210218 return Err ( err) ;
211219 }
@@ -301,20 +309,25 @@ pub fn parse_asm_args<'a>(
301309 dcx. emit_err ( errors:: AsmMayUnwind { labels_sp } ) ;
302310 }
303311
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- } ) ;
312+ if !args. clobber_abis . is_empty ( ) {
313+ match asm_macro {
314+ AsmMacro :: GlobalAsm | AsmMacro :: NakedAsm => {
315+ let err = dcx. create_err ( errors:: AsmUnsupportedClobberAbi {
316+ spans : args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect ( ) ,
317+ macro_name : asm_macro. macro_name ( ) ,
318+ } ) ;
309319
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- } ) ;
320+ // Bail out now since this is likely to confuse later stages
321+ return Err ( err) ;
322+ }
323+ AsmMacro :: Asm => {
324+ if !regclass_outputs. is_empty ( ) {
325+ dcx. emit_err ( errors:: AsmClobberNoReg {
326+ spans : regclass_outputs,
327+ clobbers : args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect ( ) ,
328+ } ) ;
329+ }
330+ }
318331 }
319332 }
320333
@@ -335,10 +348,15 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
335348///
336349/// This function must be called immediately after the option token is parsed.
337350/// Otherwise, the suggestion will be incorrect.
338- fn err_unsupported_option ( p : & Parser < ' _ > , symbol : Symbol , span : Span ) {
351+ fn err_unsupported_option ( p : & Parser < ' _ > , asm_macro : AsmMacro , symbol : Symbol , span : Span ) {
339352 // Tool-only output
340353 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 } ) ;
354+ p. dcx ( ) . emit_err ( errors:: AsmUnsupportedOption {
355+ span,
356+ symbol,
357+ full_span,
358+ macro_name : asm_macro. macro_name ( ) ,
359+ } ) ;
342360}
343361
344362/// Try to set the provided option in the provided `AsmArgs`.
@@ -349,12 +367,12 @@ fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
349367fn try_set_option < ' a > (
350368 p : & Parser < ' a > ,
351369 args : & mut AsmArgs ,
352- is_global_asm : bool ,
370+ asm_macro : AsmMacro ,
353371 symbol : Symbol ,
354372 option : ast:: InlineAsmOptions ,
355373) {
356- if is_global_asm && !ast :: InlineAsmOptions :: GLOBAL_OPTIONS . contains ( option) {
357- err_unsupported_option ( p, symbol, p. prev_token . span ) ;
374+ if !asm_macro . is_supported_option ( option) {
375+ err_unsupported_option ( p, asm_macro , symbol, p. prev_token . span ) ;
358376 } else if args. options . contains ( option) {
359377 err_duplicate_option ( p, symbol, p. prev_token . span ) ;
360378 } else {
@@ -365,7 +383,7 @@ fn try_set_option<'a>(
365383fn parse_options < ' a > (
366384 p : & mut Parser < ' a > ,
367385 args : & mut AsmArgs ,
368- is_global_asm : bool ,
386+ asm_macro : AsmMacro ,
369387) -> PResult < ' a , ( ) > {
370388 let span_start = p. prev_token . span ;
371389
@@ -386,15 +404,14 @@ fn parse_options<'a>(
386404
387405 ' blk: {
388406 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- } ;
407+ let kw_matched = if asm_macro. is_supported_option ( option) {
408+ p. eat_keyword ( symbol)
409+ } else {
410+ p. eat_keyword_noexpect ( symbol)
411+ } ;
395412
396413 if kw_matched {
397- try_set_option ( p, args, is_global_asm , symbol, option) ;
414+ try_set_option ( p, args, asm_macro , symbol, option) ;
398415 break ' blk;
399416 }
400417 }
@@ -483,7 +500,7 @@ fn parse_reg<'a>(
483500
484501fn expand_preparsed_asm (
485502 ecx : & mut ExtCtxt < ' _ > ,
486- asm_macro : ast :: AsmMacro ,
503+ asm_macro : AsmMacro ,
487504 args : AsmArgs ,
488505) -> ExpandResult < Result < ast:: InlineAsm , ErrorGuaranteed > , ( ) > {
489506 let mut template = vec ! [ ] ;
@@ -797,7 +814,7 @@ pub(super) fn expand_asm<'cx>(
797814 sp : Span ,
798815 tts : TokenStream ,
799816) -> MacroExpanderResult < ' cx > {
800- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, false ) {
817+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: Asm ) {
801818 Ok ( args) => {
802819 let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: Asm , args) else {
803820 return ExpandResult :: Retry ( ( ) ) ;
@@ -826,29 +843,20 @@ pub(super) fn expand_naked_asm<'cx>(
826843 sp : Span ,
827844 tts : TokenStream ,
828845) -> MacroExpanderResult < ' cx > {
829- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, false ) {
846+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: NakedAsm ) {
830847 Ok ( args) => {
831848 let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: NakedAsm , args)
832849 else {
833850 return ExpandResult :: Retry ( ( ) ) ;
834851 } ;
835852 let expr = match mac {
836- Ok ( mut inline_asm) => {
837- // for future compatibility, we always set the NORETURN option.
838- //
839- // When we turn `asm!` into `naked_asm!` with this implementation, we can drop
840- // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!`
841- // starts disallowing the `noreturn` option in the future
842- inline_asm. options |= ast:: InlineAsmOptions :: NORETURN ;
843-
844- P ( ast:: Expr {
845- id : ast:: DUMMY_NODE_ID ,
846- kind : ast:: ExprKind :: InlineAsm ( P ( inline_asm) ) ,
847- span : sp,
848- attrs : ast:: AttrVec :: new ( ) ,
849- tokens : None ,
850- } )
851- }
853+ Ok ( inline_asm) => P ( ast:: Expr {
854+ id : ast:: DUMMY_NODE_ID ,
855+ kind : ast:: ExprKind :: InlineAsm ( P ( inline_asm) ) ,
856+ span : sp,
857+ attrs : ast:: AttrVec :: new ( ) ,
858+ tokens : None ,
859+ } ) ,
852860 Err ( guar) => DummyResult :: raw_expr ( sp, Some ( guar) ) ,
853861 } ;
854862 MacEager :: expr ( expr)
@@ -865,7 +873,7 @@ pub(super) fn expand_global_asm<'cx>(
865873 sp : Span ,
866874 tts : TokenStream ,
867875) -> MacroExpanderResult < ' cx > {
868- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, true ) {
876+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: GlobalAsm ) {
869877 Ok ( args) => {
870878 let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: GlobalAsm , args)
871879 else {
0 commit comments