@@ -37,15 +37,23 @@ pub struct AsmArgs {
37
37
/// - `Ok(true)` if the current token matches the keyword, and was expected
38
38
/// - `Ok(false)` if the current token does not match the keyword
39
39
/// - `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 ) {
42
46
Ok ( p. eat_keyword ( symbol) )
43
47
} else {
44
48
let span = p. token . span ;
45
49
if p. eat_keyword_noexpect ( symbol) {
46
50
// in gets printed as `r#in` otherwise
47
51
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
+ } ) )
49
57
} else {
50
58
Ok ( false )
51
59
}
@@ -56,18 +64,18 @@ fn parse_args<'a>(
56
64
ecx : & ExtCtxt < ' a > ,
57
65
sp : Span ,
58
66
tts : TokenStream ,
59
- is_global_asm : bool ,
67
+ asm_macro : AsmMacro ,
60
68
) -> PResult < ' a , AsmArgs > {
61
69
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 )
63
71
}
64
72
65
73
// Primarily public for rustfmt consumption.
66
74
// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
67
75
pub fn parse_asm_args < ' a > (
68
76
p : & mut Parser < ' a > ,
69
77
sp : Span ,
70
- is_global_asm : bool ,
78
+ asm_macro : AsmMacro ,
71
79
) -> PResult < ' a , AsmArgs > {
72
80
let dcx = p. dcx ( ) ;
73
81
@@ -110,7 +118,7 @@ pub fn parse_asm_args<'a>(
110
118
111
119
// Parse options
112
120
if p. eat_keyword ( sym:: options) {
113
- parse_options ( p, & mut args, is_global_asm ) ?;
121
+ parse_options ( p, & mut args, asm_macro ) ?;
114
122
allow_templates = false ;
115
123
continue ;
116
124
}
@@ -129,23 +137,23 @@ pub fn parse_asm_args<'a>(
129
137
} ;
130
138
131
139
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 ) ? {
133
141
let reg = parse_reg ( p, & mut explicit_reg) ?;
134
142
if p. eat_keyword ( kw:: Underscore ) {
135
143
let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
136
144
return Err ( err) ;
137
145
}
138
146
let expr = p. parse_expr ( ) ?;
139
147
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 ) ? {
141
149
let reg = parse_reg ( p, & mut explicit_reg) ?;
142
150
let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
143
151
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 ) ? {
145
153
let reg = parse_reg ( p, & mut explicit_reg) ?;
146
154
let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
147
155
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 ) ? {
149
157
let reg = parse_reg ( p, & mut explicit_reg) ?;
150
158
if p. eat_keyword ( kw:: Underscore ) {
151
159
let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
@@ -159,7 +167,7 @@ pub fn parse_asm_args<'a>(
159
167
} else {
160
168
ast:: InlineAsmOperand :: InOut { reg, expr, late : false }
161
169
}
162
- } else if eat_operand_keyword ( p, sym:: inlateout, !is_global_asm ) ? {
170
+ } else if eat_operand_keyword ( p, sym:: inlateout, asm_macro ) ? {
163
171
let reg = parse_reg ( p, & mut explicit_reg) ?;
164
172
if p. eat_keyword ( kw:: Underscore ) {
165
173
let err = dcx. create_err ( errors:: AsmUnderscoreInput { span : p. token . span } ) ;
@@ -173,7 +181,7 @@ pub fn parse_asm_args<'a>(
173
181
} else {
174
182
ast:: InlineAsmOperand :: InOut { reg, expr, late : true }
175
183
}
176
- } else if eat_operand_keyword ( p, sym:: label, !is_global_asm ) ? {
184
+ } else if eat_operand_keyword ( p, sym:: label, asm_macro ) ? {
177
185
let block = p. parse_block ( ) ?;
178
186
ast:: InlineAsmOperand :: Label { block }
179
187
} else if p. eat_keyword ( kw:: Const ) {
@@ -205,7 +213,7 @@ pub fn parse_asm_args<'a>(
205
213
_ => {
206
214
let err = dcx. create_err ( errors:: AsmExpectedOther {
207
215
span : template. span ,
208
- is_global_asm ,
216
+ is_inline_asm : matches ! ( asm_macro , AsmMacro :: Asm ) ,
209
217
} ) ;
210
218
return Err ( err) ;
211
219
}
@@ -301,20 +309,25 @@ pub fn parse_asm_args<'a>(
301
309
dcx. emit_err ( errors:: AsmMayUnwind { labels_sp } ) ;
302
310
}
303
311
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
+ } ) ;
309
319
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
+ }
318
331
}
319
332
}
320
333
@@ -335,10 +348,15 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
335
348
///
336
349
/// This function must be called immediately after the option token is parsed.
337
350
/// 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 ) {
339
352
// Tool-only output
340
353
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
+ } ) ;
342
360
}
343
361
344
362
/// Try to set the provided option in the provided `AsmArgs`.
@@ -349,12 +367,12 @@ fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
349
367
fn try_set_option < ' a > (
350
368
p : & Parser < ' a > ,
351
369
args : & mut AsmArgs ,
352
- is_global_asm : bool ,
370
+ asm_macro : AsmMacro ,
353
371
symbol : Symbol ,
354
372
option : ast:: InlineAsmOptions ,
355
373
) {
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 ) ;
358
376
} else if args. options . contains ( option) {
359
377
err_duplicate_option ( p, symbol, p. prev_token . span ) ;
360
378
} else {
@@ -365,7 +383,7 @@ fn try_set_option<'a>(
365
383
fn parse_options < ' a > (
366
384
p : & mut Parser < ' a > ,
367
385
args : & mut AsmArgs ,
368
- is_global_asm : bool ,
386
+ asm_macro : AsmMacro ,
369
387
) -> PResult < ' a , ( ) > {
370
388
let span_start = p. prev_token . span ;
371
389
@@ -386,15 +404,14 @@ fn parse_options<'a>(
386
404
387
405
' blk: {
388
406
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
+ } ;
395
412
396
413
if kw_matched {
397
- try_set_option ( p, args, is_global_asm , symbol, option) ;
414
+ try_set_option ( p, args, asm_macro , symbol, option) ;
398
415
break ' blk;
399
416
}
400
417
}
@@ -483,7 +500,7 @@ fn parse_reg<'a>(
483
500
484
501
fn expand_preparsed_asm (
485
502
ecx : & mut ExtCtxt < ' _ > ,
486
- asm_macro : ast :: AsmMacro ,
503
+ asm_macro : AsmMacro ,
487
504
args : AsmArgs ,
488
505
) -> ExpandResult < Result < ast:: InlineAsm , ErrorGuaranteed > , ( ) > {
489
506
let mut template = vec ! [ ] ;
@@ -797,7 +814,7 @@ pub(super) fn expand_asm<'cx>(
797
814
sp : Span ,
798
815
tts : TokenStream ,
799
816
) -> MacroExpanderResult < ' cx > {
800
- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, false ) {
817
+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: Asm ) {
801
818
Ok ( args) => {
802
819
let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: Asm , args) else {
803
820
return ExpandResult :: Retry ( ( ) ) ;
@@ -826,29 +843,20 @@ pub(super) fn expand_naked_asm<'cx>(
826
843
sp : Span ,
827
844
tts : TokenStream ,
828
845
) -> MacroExpanderResult < ' cx > {
829
- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, false ) {
846
+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: NakedAsm ) {
830
847
Ok ( args) => {
831
848
let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: NakedAsm , args)
832
849
else {
833
850
return ExpandResult :: Retry ( ( ) ) ;
834
851
} ;
835
852
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
+ } ) ,
852
860
Err ( guar) => DummyResult :: raw_expr ( sp, Some ( guar) ) ,
853
861
} ;
854
862
MacEager :: expr ( expr)
@@ -865,7 +873,7 @@ pub(super) fn expand_global_asm<'cx>(
865
873
sp : Span ,
866
874
tts : TokenStream ,
867
875
) -> MacroExpanderResult < ' cx > {
868
- ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, true ) {
876
+ ExpandResult :: Ready ( match parse_args ( ecx, sp, tts, AsmMacro :: GlobalAsm ) {
869
877
Ok ( args) => {
870
878
let ExpandResult :: Ready ( mac) = expand_preparsed_asm ( ecx, AsmMacro :: GlobalAsm , args)
871
879
else {
0 commit comments