@@ -8,13 +8,14 @@ use rustc_expand::base::{self, *};
88use rustc_parse:: parser:: Parser ;
99use rustc_parse_format as parse;
1010use rustc_session:: lint;
11+ use rustc_session:: parse:: ParseSess ;
1112use rustc_span:: symbol:: Ident ;
1213use rustc_span:: symbol:: { kw, sym, Symbol } ;
1314use rustc_span:: { InnerSpan , Span } ;
1415use rustc_target:: asm:: InlineAsmArch ;
1516use smallvec:: smallvec;
1617
17- struct AsmArgs {
18+ pub struct AsmArgs {
1819 templates : Vec < P < ast:: Expr > > ,
1920 operands : Vec < ( ast:: InlineAsmOperand , Span ) > ,
2021 named_args : FxHashMap < Symbol , usize > ,
@@ -31,15 +32,28 @@ fn parse_args<'a>(
3132 is_global_asm : bool ,
3233) -> Result < AsmArgs , DiagnosticBuilder < ' a > > {
3334 let mut p = ecx. new_parser_from_tts ( tts) ;
35+ let sess = & ecx. sess . parse_sess ;
36+ parse_asm_args ( & mut p, sess, sp, is_global_asm)
37+ }
38+
39+ // Primarily public for rustfmt consumption.
40+ // Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
41+ pub fn parse_asm_args < ' a > (
42+ p : & mut Parser < ' a > ,
43+ sess : & ' a ParseSess ,
44+ sp : Span ,
45+ is_global_asm : bool ,
46+ ) -> Result < AsmArgs , DiagnosticBuilder < ' a > > {
47+ let diag = & sess. span_diagnostic ;
3448
3549 if p. token == token:: Eof {
36- return Err ( ecx . struct_span_err ( sp, "requires at least a template string argument" ) ) ;
50+ return Err ( diag . struct_span_err ( sp, "requires at least a template string argument" ) ) ;
3751 }
3852
3953 // Detect use of the legacy llvm_asm! syntax (which used to be called asm!)
4054 if !is_global_asm && p. look_ahead ( 1 , |t| * t == token:: Colon || * t == token:: ModSep ) {
4155 let mut err =
42- ecx . struct_span_err ( sp, "the legacy LLVM-style asm! syntax is no longer supported" ) ;
56+ diag . struct_span_err ( sp, "the legacy LLVM-style asm! syntax is no longer supported" ) ;
4357 err. note ( "consider migrating to the new asm! syntax specified in RFC 2873" ) ;
4458 err. note ( "alternatively, switch to llvm_asm! to keep your code working as it is" ) ;
4559 return Err ( err) ;
@@ -61,7 +75,7 @@ fn parse_args<'a>(
6175 if !p. eat ( & token:: Comma ) {
6276 if allow_templates {
6377 // After a template string, we always expect *only* a comma...
64- let mut err = ecx . struct_span_err ( p. token . span , "expected token: `,`" ) ;
78+ let mut err = diag . struct_span_err ( p. token . span , "expected token: `,`" ) ;
6579 err. span_label ( p. token . span , "expected `,`" ) ;
6680 p. maybe_annotate_with_ascription ( & mut err, false ) ;
6781 return Err ( err) ;
@@ -76,14 +90,14 @@ fn parse_args<'a>(
7690
7791 // Parse clobber_abi
7892 if p. eat_keyword ( sym:: clobber_abi) {
79- parse_clobber_abi ( & mut p, & mut args) ?;
93+ parse_clobber_abi ( p, & mut args) ?;
8094 allow_templates = false ;
8195 continue ;
8296 }
8397
8498 // Parse options
8599 if p. eat_keyword ( sym:: options) {
86- parse_options ( & mut p, & mut args, is_global_asm) ?;
100+ parse_options ( p, & mut args, is_global_asm) ?;
87101 allow_templates = false ;
88102 continue ;
89103 }
@@ -103,25 +117,25 @@ fn parse_args<'a>(
103117
104118 let mut explicit_reg = false ;
105119 let op = if !is_global_asm && p. eat_keyword ( kw:: In ) {
106- let reg = parse_reg ( & mut p, & mut explicit_reg) ?;
120+ let reg = parse_reg ( p, & mut explicit_reg) ?;
107121 if p. eat_keyword ( kw:: Underscore ) {
108- let err = ecx . struct_span_err ( p. token . span , "_ cannot be used for input operands" ) ;
122+ let err = diag . struct_span_err ( p. token . span , "_ cannot be used for input operands" ) ;
109123 return Err ( err) ;
110124 }
111125 let expr = p. parse_expr ( ) ?;
112126 ast:: InlineAsmOperand :: In { reg, expr }
113127 } else if !is_global_asm && p. eat_keyword ( sym:: out) {
114- let reg = parse_reg ( & mut p, & mut explicit_reg) ?;
128+ let reg = parse_reg ( p, & mut explicit_reg) ?;
115129 let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
116130 ast:: InlineAsmOperand :: Out { reg, expr, late : false }
117131 } else if !is_global_asm && p. eat_keyword ( sym:: lateout) {
118- let reg = parse_reg ( & mut p, & mut explicit_reg) ?;
132+ let reg = parse_reg ( p, & mut explicit_reg) ?;
119133 let expr = if p. eat_keyword ( kw:: Underscore ) { None } else { Some ( p. parse_expr ( ) ?) } ;
120134 ast:: InlineAsmOperand :: Out { reg, expr, late : true }
121135 } else if !is_global_asm && p. eat_keyword ( sym:: inout) {
122- let reg = parse_reg ( & mut p, & mut explicit_reg) ?;
136+ let reg = parse_reg ( p, & mut explicit_reg) ?;
123137 if p. eat_keyword ( kw:: Underscore ) {
124- let err = ecx . struct_span_err ( p. token . span , "_ cannot be used for input operands" ) ;
138+ let err = diag . struct_span_err ( p. token . span , "_ cannot be used for input operands" ) ;
125139 return Err ( err) ;
126140 }
127141 let expr = p. parse_expr ( ) ?;
@@ -133,9 +147,9 @@ fn parse_args<'a>(
133147 ast:: InlineAsmOperand :: InOut { reg, expr, late : false }
134148 }
135149 } else if !is_global_asm && p. eat_keyword ( sym:: inlateout) {
136- let reg = parse_reg ( & mut p, & mut explicit_reg) ?;
150+ let reg = parse_reg ( p, & mut explicit_reg) ?;
137151 if p. eat_keyword ( kw:: Underscore ) {
138- let err = ecx . struct_span_err ( p. token . span , "_ cannot be used for input operands" ) ;
152+ let err = diag . struct_span_err ( p. token . span , "_ cannot be used for input operands" ) ;
139153 return Err ( err) ;
140154 }
141155 let expr = p. parse_expr ( ) ?;
@@ -154,7 +168,7 @@ fn parse_args<'a>(
154168 match expr. kind {
155169 ast:: ExprKind :: Path ( ..) => { }
156170 _ => {
157- let err = ecx
171+ let err = diag
158172 . struct_span_err ( expr. span , "argument to `sym` must be a path expression" ) ;
159173 return Err ( err) ;
160174 }
@@ -173,7 +187,7 @@ fn parse_args<'a>(
173187 } else {
174188 "expected operand, clobber_abi, options, or additional template string"
175189 } ;
176- let mut err = ecx . struct_span_err ( template. span , errstr) ;
190+ let mut err = diag . struct_span_err ( template. span , errstr) ;
177191 err. span_label ( template. span , errstr) ;
178192 return Err ( err) ;
179193 }
@@ -193,31 +207,31 @@ fn parse_args<'a>(
193207 // clobber_abi/options. We do this at the end once we have the full span
194208 // of the argument available.
195209 if !args. options_spans . is_empty ( ) {
196- ecx . struct_span_err ( span, "arguments are not allowed after options" )
210+ diag . struct_span_err ( span, "arguments are not allowed after options" )
197211 . span_labels ( args. options_spans . clone ( ) , "previous options" )
198212 . span_label ( span, "argument" )
199213 . emit ( ) ;
200214 } else if let Some ( ( _, abi_span) ) = args. clobber_abis . last ( ) {
201- ecx . struct_span_err ( span, "arguments are not allowed after clobber_abi" )
215+ diag . struct_span_err ( span, "arguments are not allowed after clobber_abi" )
202216 . span_label ( * abi_span, "clobber_abi" )
203217 . span_label ( span, "argument" )
204218 . emit ( ) ;
205219 }
206220 if explicit_reg {
207221 if name. is_some ( ) {
208- ecx . struct_span_err ( span, "explicit register arguments cannot have names" ) . emit ( ) ;
222+ diag . struct_span_err ( span, "explicit register arguments cannot have names" ) . emit ( ) ;
209223 }
210224 args. reg_args . insert ( slot) ;
211225 } else if let Some ( name) = name {
212226 if let Some ( & prev) = args. named_args . get ( & name) {
213- ecx . struct_span_err ( span, & format ! ( "duplicate argument named `{}`" , name) )
227+ diag . struct_span_err ( span, & format ! ( "duplicate argument named `{}`" , name) )
214228 . span_label ( args. operands [ prev] . 1 , "previously here" )
215229 . span_label ( span, "duplicate argument" )
216230 . emit ( ) ;
217231 continue ;
218232 }
219233 if !args. reg_args . is_empty ( ) {
220- let mut err = ecx . struct_span_err (
234+ let mut err = diag . struct_span_err (
221235 span,
222236 "named arguments cannot follow explicit register arguments" ,
223237 ) ;
@@ -230,7 +244,7 @@ fn parse_args<'a>(
230244 args. named_args . insert ( name, slot) ;
231245 } else {
232246 if !args. named_args . is_empty ( ) || !args. reg_args . is_empty ( ) {
233- let mut err = ecx . struct_span_err (
247+ let mut err = diag . struct_span_err (
234248 span,
235249 "positional arguments cannot follow named arguments \
236250 or explicit register arguments",
@@ -251,21 +265,21 @@ fn parse_args<'a>(
251265 && args. options . contains ( ast:: InlineAsmOptions :: READONLY )
252266 {
253267 let spans = args. options_spans . clone ( ) ;
254- ecx . struct_span_err ( spans, "the `nomem` and `readonly` options are mutually exclusive" )
268+ diag . struct_span_err ( spans, "the `nomem` and `readonly` options are mutually exclusive" )
255269 . emit ( ) ;
256270 }
257271 if args. options . contains ( ast:: InlineAsmOptions :: PURE )
258272 && args. options . contains ( ast:: InlineAsmOptions :: NORETURN )
259273 {
260274 let spans = args. options_spans . clone ( ) ;
261- ecx . struct_span_err ( spans, "the `pure` and `noreturn` options are mutually exclusive" )
275+ diag . struct_span_err ( spans, "the `pure` and `noreturn` options are mutually exclusive" )
262276 . emit ( ) ;
263277 }
264278 if args. options . contains ( ast:: InlineAsmOptions :: PURE )
265279 && !args. options . intersects ( ast:: InlineAsmOptions :: NOMEM | ast:: InlineAsmOptions :: READONLY )
266280 {
267281 let spans = args. options_spans . clone ( ) ;
268- ecx . struct_span_err (
282+ diag . struct_span_err (
269283 spans,
270284 "the `pure` option must be combined with either `nomem` or `readonly`" ,
271285 )
@@ -296,14 +310,14 @@ fn parse_args<'a>(
296310 }
297311 }
298312 if args. options . contains ( ast:: InlineAsmOptions :: PURE ) && !have_real_output {
299- ecx . struct_span_err (
313+ diag . struct_span_err (
300314 args. options_spans . clone ( ) ,
301315 "asm with the `pure` option must have at least one output" ,
302316 )
303317 . emit ( ) ;
304318 }
305319 if args. options . contains ( ast:: InlineAsmOptions :: NORETURN ) && !outputs_sp. is_empty ( ) {
306- let err = ecx
320+ let err = diag
307321 . struct_span_err ( outputs_sp, "asm outputs are not allowed with the `noreturn` option" ) ;
308322
309323 // Bail out now since this is likely to confuse MIR
@@ -312,7 +326,7 @@ fn parse_args<'a>(
312326
313327 if args. clobber_abis . len ( ) > 0 {
314328 if is_global_asm {
315- let err = ecx . struct_span_err (
329+ let err = diag . struct_span_err (
316330 args. clobber_abis . iter ( ) . map ( |( _, span) | * span) . collect :: < Vec < Span > > ( ) ,
317331 "`clobber_abi` cannot be used with `global_asm!`" ,
318332 ) ;
@@ -321,7 +335,7 @@ fn parse_args<'a>(
321335 return Err ( err) ;
322336 }
323337 if !regclass_outputs. is_empty ( ) {
324- ecx . struct_span_err (
338+ diag . struct_span_err (
325339 regclass_outputs. clone ( ) ,
326340 "asm with `clobber_abi` must specify explicit registers for outputs" ,
327341 )
0 commit comments