@@ -4,7 +4,7 @@ use rustc_ast::ptr::P;
4
4
use rustc_ast:: tokenstream:: TokenStream ;
5
5
use rustc_ast:: { AsmMacro , token} ;
6
6
use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
7
- use rustc_errors:: PResult ;
7
+ use rustc_errors:: { DiagCtxtHandle , PResult } ;
8
8
use rustc_expand:: base:: * ;
9
9
use rustc_index:: bit_set:: GrowableBitSet ;
10
10
use rustc_parse:: exp;
@@ -18,10 +18,11 @@ use {rustc_ast as ast, rustc_parse_format as parse};
18
18
use crate :: errors;
19
19
use crate :: util:: { ExprToSpannedString , expr_to_spanned_string} ;
20
20
21
+ /// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
22
+ /// not validated at all.
21
23
pub struct RawAsmArg {
22
- pub span : Span ,
23
- pub attributes : ast:: AttrVec ,
24
24
pub kind : RawAsmArgKind ,
25
+ pub span : Span ,
25
26
}
26
27
27
28
pub enum RawAsmArgKind {
@@ -31,6 +32,7 @@ pub enum RawAsmArgKind {
31
32
ClobberAbi ( Vec < ( Symbol , Span ) > ) ,
32
33
}
33
34
35
+ /// Validated assembly arguments, ready for macro expansion.
34
36
pub struct AsmArgs {
35
37
pub templates : Vec < P < ast:: Expr > > ,
36
38
pub operands : Vec < ( ast:: InlineAsmOperand , Span ) > ,
@@ -72,16 +74,6 @@ fn eat_operand_keyword<'a>(
72
74
}
73
75
}
74
76
75
- fn parse_args < ' a > (
76
- ecx : & ExtCtxt < ' a > ,
77
- sp : Span ,
78
- tts : TokenStream ,
79
- asm_macro : AsmMacro ,
80
- ) -> PResult < ' a , AsmArgs > {
81
- let mut p = ecx. new_parser_from_tts ( tts) ;
82
- parse_asm_args ( & mut p, sp, asm_macro)
83
- }
84
-
85
77
fn parse_asm_operand < ' a > (
86
78
p : & mut Parser < ' a > ,
87
79
asm_macro : AsmMacro ,
@@ -168,7 +160,6 @@ pub fn parse_raw_asm_args<'a>(
168
160
let first_template = p. parse_expr ( ) ?;
169
161
args. push ( RawAsmArg {
170
162
span : first_template. span ,
171
- attributes : ast:: AttrVec :: new ( ) ,
172
163
kind : RawAsmArgKind :: Template ( first_template) ,
173
164
} ) ;
174
165
@@ -195,7 +186,6 @@ pub fn parse_raw_asm_args<'a>(
195
186
allow_templates = false ;
196
187
197
188
args. push ( RawAsmArg {
198
- attributes : ast:: AttrVec :: new ( ) ,
199
189
kind : RawAsmArgKind :: ClobberAbi ( parse_clobber_abi ( p) ?) ,
200
190
span : span_start. to ( p. prev_token . span ) ,
201
191
} ) ;
@@ -208,7 +198,6 @@ pub fn parse_raw_asm_args<'a>(
208
198
allow_templates = false ;
209
199
210
200
args. push ( RawAsmArg {
211
- attributes : ast:: AttrVec :: new ( ) ,
212
201
kind : RawAsmArgKind :: Options ( parse_options ( p, asm_macro) ?) ,
213
202
span : span_start. to ( p. prev_token . span ) ,
214
203
} ) ;
@@ -227,58 +216,68 @@ pub fn parse_raw_asm_args<'a>(
227
216
None
228
217
} ;
229
218
230
- let Some ( op) = parse_asm_operand ( p, asm_macro) ? else {
231
- if allow_templates {
232
- let template = p. parse_expr ( ) ?;
233
- // If it can't possibly expand to a string, provide diagnostics here to include other
234
- // things it could have been.
235
- match template. kind {
236
- ast:: ExprKind :: Lit ( token_lit)
237
- if matches ! (
238
- token_lit. kind,
239
- token:: LitKind :: Str | token:: LitKind :: StrRaw ( _)
240
- ) => { }
241
- ast:: ExprKind :: MacCall ( ..) => { }
242
- _ => {
243
- let err = dcx. create_err ( errors:: AsmExpectedOther {
244
- span : template. span ,
245
- is_inline_asm : matches ! ( asm_macro, AsmMacro :: Asm ) ,
246
- } ) ;
247
- return Err ( err) ;
248
- }
249
- }
250
-
251
- args. push ( RawAsmArg {
252
- span : template. span ,
253
- attributes : ast:: AttrVec :: new ( ) ,
254
- kind : RawAsmArgKind :: Template ( template) ,
255
- } ) ;
219
+ if let Some ( op) = parse_asm_operand ( p, asm_macro) ? {
220
+ allow_templates = false ;
256
221
257
- continue ;
258
- } else {
259
- p. unexpected_any ( ) ?
222
+ args. push ( RawAsmArg {
223
+ span : span_start. to ( p. prev_token . span ) ,
224
+ kind : RawAsmArgKind :: Operand ( name, op) ,
225
+ } ) ;
226
+ } else if allow_templates {
227
+ let template = p. parse_expr ( ) ?;
228
+ // If it can't possibly expand to a string, provide diagnostics here to include other
229
+ // things it could have been.
230
+ match template. kind {
231
+ ast:: ExprKind :: Lit ( token_lit)
232
+ if matches ! (
233
+ token_lit. kind,
234
+ token:: LitKind :: Str | token:: LitKind :: StrRaw ( _)
235
+ ) => { }
236
+ ast:: ExprKind :: MacCall ( ..) => { }
237
+ _ => {
238
+ let err = dcx. create_err ( errors:: AsmExpectedOther {
239
+ span : template. span ,
240
+ is_inline_asm : matches ! ( asm_macro, AsmMacro :: Asm ) ,
241
+ } ) ;
242
+ return Err ( err) ;
243
+ }
260
244
}
261
- } ;
262
245
263
- allow_templates = false ;
264
-
265
- args. push ( RawAsmArg {
266
- span : span_start. to ( p. prev_token . span ) ,
267
- attributes : ast:: AttrVec :: new ( ) ,
268
- kind : RawAsmArgKind :: Operand ( name, op) ,
269
- } ) ;
246
+ args. push ( RawAsmArg { span : template. span , kind : RawAsmArgKind :: Template ( template) } ) ;
247
+ } else {
248
+ p. unexpected_any ( ) ?
249
+ }
270
250
}
271
251
272
252
Ok ( args)
273
253
}
274
254
255
+ fn parse_args < ' a > (
256
+ ecx : & ExtCtxt < ' a > ,
257
+ sp : Span ,
258
+ tts : TokenStream ,
259
+ asm_macro : AsmMacro ,
260
+ ) -> PResult < ' a , AsmArgs > {
261
+ let mut p = ecx. new_parser_from_tts ( tts) ;
262
+ parse_asm_args ( & mut p, sp, asm_macro)
263
+ }
264
+
265
+ // public for use in rustfmt
266
+ // FIXME: use `RawAsmArg` in the formatting code instead.
275
267
pub fn parse_asm_args < ' a > (
276
268
p : & mut Parser < ' a > ,
277
269
sp : Span ,
278
270
asm_macro : AsmMacro ,
279
271
) -> PResult < ' a , AsmArgs > {
280
- let dcx = p. dcx ( ) ;
272
+ let raw_args = parse_raw_asm_args ( p, sp, asm_macro) ?;
273
+ validate_raw_asm_args ( p. dcx ( ) , asm_macro, raw_args)
274
+ }
281
275
276
+ pub fn validate_raw_asm_args < ' a > (
277
+ dcx : DiagCtxtHandle < ' a > ,
278
+ asm_macro : AsmMacro ,
279
+ raw_args : Vec < RawAsmArg > ,
280
+ ) -> PResult < ' a , AsmArgs > {
282
281
let mut args = AsmArgs {
283
282
templates : vec ! [ ] ,
284
283
operands : vec ! [ ] ,
@@ -291,12 +290,11 @@ pub fn parse_asm_args<'a>(
291
290
292
291
let mut allow_templates = true ;
293
292
294
- for arg in parse_raw_asm_args ( p , sp , asm_macro ) ? {
293
+ for arg in raw_args {
295
294
match arg. kind {
296
295
RawAsmArgKind :: Template ( template) => {
297
- if allow_templates {
298
- args. templates . push ( template) ;
299
- } else {
296
+ // The error for the first template is delayed.
297
+ if !allow_templates {
300
298
match template. kind {
301
299
ast:: ExprKind :: Lit ( token_lit)
302
300
if matches ! (
@@ -312,14 +310,14 @@ pub fn parse_asm_args<'a>(
312
310
return Err ( err) ;
313
311
}
314
312
}
315
- args. templates . push ( template) ;
316
313
}
314
+
315
+ args. templates . push ( template) ;
317
316
}
318
317
RawAsmArgKind :: Operand ( name, op) => {
319
318
allow_templates = false ;
320
319
321
320
let explicit_reg = matches ! ( op. reg( ) , Some ( ast:: InlineAsmRegOrRegClass :: Reg ( _) ) ) ;
322
-
323
321
let span = arg. span ;
324
322
let slot = args. operands . len ( ) ;
325
323
args. operands . push ( ( op, span) ) ;
@@ -366,7 +364,7 @@ pub fn parse_asm_args<'a>(
366
364
*/
367
365
} else if args. options . contains ( option) {
368
366
// Tool-only output
369
- p . dcx ( ) . emit_err ( errors:: AsmOptAlreadyprovided { span, symbol, full_span } ) ;
367
+ dcx. emit_err ( errors:: AsmOptAlreadyprovided { span, symbol, full_span } ) ;
370
368
} else {
371
369
args. options |= option;
372
370
}
@@ -496,6 +494,7 @@ fn parse_options<'a>(
496
494
497
495
' blk: {
498
496
for ( exp, option) in OPTIONS {
497
+ // Gives a more accurate list of expected next tokens.
499
498
let kw_matched = if asm_macro. is_supported_option ( option) {
500
499
p. eat_keyword ( exp)
501
500
} else {
@@ -538,7 +537,6 @@ fn parse_options<'a>(
538
537
fn parse_clobber_abi < ' a > ( p : & mut Parser < ' a > ) -> PResult < ' a , Vec < ( Symbol , Span ) > > {
539
538
p. expect ( exp ! ( OpenParen ) ) ?;
540
539
541
- // FIXME: why not allow this?
542
540
if p. eat ( exp ! ( CloseParen ) ) {
543
541
return Err ( p. dcx ( ) . create_err ( errors:: NonABI { span : p. token . span } ) ) ;
544
542
}
0 commit comments