@@ -4,6 +4,7 @@ use self::State::*;
4
4
5
5
use rustc_data_structures:: thin_vec:: ThinVec ;
6
6
7
+ use errors:: DiagnosticBuilder ;
7
8
use syntax:: ast;
8
9
use syntax:: ext:: base;
9
10
use syntax:: ext:: base:: * ;
@@ -51,6 +52,34 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
51
52
feature_gate:: EXPLAIN_ASM ) ;
52
53
}
53
54
55
+ let mut inline_asm = match parse_inline_asm ( cx, sp, tts) {
56
+ Ok ( Some ( inline_asm) ) => inline_asm,
57
+ Ok ( None ) => return DummyResult :: expr ( sp) ,
58
+ Err ( mut err) => {
59
+ err. emit ( ) ;
60
+ return DummyResult :: expr ( sp) ;
61
+ }
62
+ } ;
63
+
64
+ // If there are no outputs, the inline assembly is executed just for its side effects,
65
+ // so ensure that it is volatile
66
+ if inline_asm. outputs . is_empty ( ) {
67
+ inline_asm. volatile = true ;
68
+ }
69
+
70
+ MacEager :: expr ( P ( ast:: Expr {
71
+ id : ast:: DUMMY_NODE_ID ,
72
+ node : ast:: ExprKind :: InlineAsm ( P ( inline_asm) ) ,
73
+ span : sp,
74
+ attrs : ThinVec :: new ( ) ,
75
+ } ) )
76
+ }
77
+
78
+ fn parse_inline_asm < ' a > (
79
+ cx : & mut ExtCtxt < ' a > ,
80
+ sp : Span ,
81
+ tts : & [ tokenstream:: TokenTree ] ,
82
+ ) -> Result < Option < ast:: InlineAsm > , DiagnosticBuilder < ' a > > {
54
83
// Split the tts before the first colon, to avoid `asm!("x": y)` being
55
84
// parsed as `asm!(z)` with `z = "x": y` which is type ascription.
56
85
let first_colon = tts. iter ( )
@@ -80,22 +109,33 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
80
109
if asm_str_style. is_some ( ) {
81
110
// If we already have a string with instructions,
82
111
// ending up in Asm state again is an error.
83
- span_err ! ( cx, sp, E0660 , "malformed inline assembly" ) ;
84
- return DummyResult :: expr ( sp) ;
112
+ return Err ( struct_span_err ! (
113
+ cx. parse_sess. span_diagnostic,
114
+ sp,
115
+ E0660 ,
116
+ "malformed inline assembly"
117
+ ) ) ;
85
118
}
86
119
// Nested parser, stop before the first colon (see above).
87
120
let mut p2 = cx. new_parser_from_tts ( & tts[ ..first_colon] ) ;
88
- let ( s, style) = match expr_to_string ( cx,
89
- panictry ! ( p2. parse_expr( ) ) ,
90
- "inline assembly must be a string literal" ) {
91
- Some ( ( s, st) ) => ( s, st) ,
92
- // let compilation continue
93
- None => return DummyResult :: expr ( sp) ,
94
- } ;
121
+
122
+ if p2. token == token:: Eof {
123
+ let mut err =
124
+ cx. struct_span_err ( sp, "macro requires a string literal as an argument" ) ;
125
+ err. span_label ( sp, "string literal required" ) ;
126
+ return Err ( err) ;
127
+ }
128
+
129
+ let expr = p2. parse_expr ( ) ?;
130
+ let ( s, style) =
131
+ match expr_to_string ( cx, expr, "inline assembly must be a string literal" ) {
132
+ Some ( ( s, st) ) => ( s, st) ,
133
+ None => return Ok ( None ) ,
134
+ } ;
95
135
96
136
// This is most likely malformed.
97
137
if p2. token != token:: Eof {
98
- let mut extra_tts = panictry ! ( p2. parse_all_token_trees( ) ) ;
138
+ let mut extra_tts = p2. parse_all_token_trees ( ) ? ;
99
139
extra_tts. extend ( tts[ first_colon..] . iter ( ) . cloned ( ) ) ;
100
140
p = parse:: stream_to_parser ( cx. parse_sess , extra_tts. into_iter ( ) . collect ( ) ) ;
101
141
}
@@ -105,18 +145,17 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
105
145
}
106
146
Outputs => {
107
147
while p. token != token:: Eof && p. token != token:: Colon && p. token != token:: ModSep {
108
-
109
148
if !outputs. is_empty ( ) {
110
149
p. eat ( & token:: Comma ) ;
111
150
}
112
151
113
- let ( constraint, _str_style ) = panictry ! ( p. parse_str( ) ) ;
152
+ let ( constraint, _ ) = p. parse_str ( ) ? ;
114
153
115
154
let span = p. prev_span ;
116
155
117
- panictry ! ( p. expect( & token:: OpenDelim ( token:: Paren ) ) ) ;
118
- let out = panictry ! ( p. parse_expr( ) ) ;
119
- panictry ! ( p. expect( & token:: CloseDelim ( token:: Paren ) ) ) ;
156
+ p. expect ( & token:: OpenDelim ( token:: Paren ) ) ? ;
157
+ let expr = p. parse_expr ( ) ? ;
158
+ p. expect ( & token:: CloseDelim ( token:: Paren ) ) ? ;
120
159
121
160
// Expands a read+write operand into two operands.
122
161
//
@@ -143,20 +182,19 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
143
182
let is_indirect = constraint_str. contains ( "*" ) ;
144
183
outputs. push ( ast:: InlineAsmOutput {
145
184
constraint : output. unwrap_or ( constraint) ,
146
- expr : out ,
185
+ expr,
147
186
is_rw,
148
187
is_indirect,
149
188
} ) ;
150
189
}
151
190
}
152
191
Inputs => {
153
192
while p. token != token:: Eof && p. token != token:: Colon && p. token != token:: ModSep {
154
-
155
193
if !inputs. is_empty ( ) {
156
194
p. eat ( & token:: Comma ) ;
157
195
}
158
196
159
- let ( constraint, _str_style ) = panictry ! ( p. parse_str( ) ) ;
197
+ let ( constraint, _ ) = p. parse_str ( ) ? ;
160
198
161
199
if constraint. as_str ( ) . starts_with ( "=" ) {
162
200
span_err ! ( cx, p. prev_span, E0662 ,
@@ -166,21 +204,20 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
166
204
"input operand constraint contains '+'" ) ;
167
205
}
168
206
169
- panictry ! ( p. expect( & token:: OpenDelim ( token:: Paren ) ) ) ;
170
- let input = panictry ! ( p. parse_expr( ) ) ;
171
- panictry ! ( p. expect( & token:: CloseDelim ( token:: Paren ) ) ) ;
207
+ p. expect ( & token:: OpenDelim ( token:: Paren ) ) ? ;
208
+ let input = p. parse_expr ( ) ? ;
209
+ p. expect ( & token:: CloseDelim ( token:: Paren ) ) ? ;
172
210
173
211
inputs. push ( ( constraint, input) ) ;
174
212
}
175
213
}
176
214
Clobbers => {
177
215
while p. token != token:: Eof && p. token != token:: Colon && p. token != token:: ModSep {
178
-
179
216
if !clobs. is_empty ( ) {
180
217
p. eat ( & token:: Comma ) ;
181
218
}
182
219
183
- let ( s, _str_style ) = panictry ! ( p. parse_str( ) ) ;
220
+ let ( s, _ ) = p. parse_str ( ) ? ;
184
221
185
222
if OPTIONS . iter ( ) . any ( |& opt| s == opt) {
186
223
cx. span_warn ( p. prev_span , "expected a clobber, found an option" ) ;
@@ -193,7 +230,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
193
230
}
194
231
}
195
232
Options => {
196
- let ( option, _str_style ) = panictry ! ( p. parse_str( ) ) ;
233
+ let ( option, _ ) = p. parse_str ( ) ? ;
197
234
198
235
if option == "volatile" {
199
236
// Indicates that the inline assembly has side effects
@@ -234,26 +271,15 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
234
271
}
235
272
}
236
273
237
- // If there are no outputs, the inline assembly is executed just for its side effects,
238
- // so ensure that it is volatile
239
- if outputs. is_empty ( ) {
240
- volatile = true ;
241
- }
242
-
243
- MacEager :: expr ( P ( ast:: Expr {
244
- id : ast:: DUMMY_NODE_ID ,
245
- node : ast:: ExprKind :: InlineAsm ( P ( ast:: InlineAsm {
246
- asm,
247
- asm_str_style : asm_str_style. unwrap ( ) ,
248
- outputs,
249
- inputs,
250
- clobbers : clobs,
251
- volatile,
252
- alignstack,
253
- dialect,
254
- ctxt : cx. backtrace ( ) ,
255
- } ) ) ,
256
- span : sp,
257
- attrs : ThinVec :: new ( ) ,
274
+ Ok ( Some ( ast:: InlineAsm {
275
+ asm,
276
+ asm_str_style : asm_str_style. unwrap ( ) ,
277
+ outputs,
278
+ inputs,
279
+ clobbers : clobs,
280
+ volatile,
281
+ alignstack,
282
+ dialect,
283
+ ctxt : cx. backtrace ( ) ,
258
284
} ) )
259
285
}
0 commit comments