10
10
11
11
use hair:: cx:: Cx ;
12
12
use rustc:: middle:: region:: { CodeExtent , CodeExtentData } ;
13
- use rustc:: ty:: { self , FnOutput , Ty } ;
13
+ use rustc:: ty:: { self , Ty } ;
14
14
use rustc:: mir:: repr:: * ;
15
15
use rustc_data_structures:: fnv:: FnvHashMap ;
16
16
use rustc:: hir;
17
17
use rustc:: hir:: pat_util:: pat_is_binding;
18
18
use std:: ops:: { Index , IndexMut } ;
19
+ use syntax:: abi:: Abi ;
19
20
use syntax:: ast;
20
21
use syntax:: codemap:: Span ;
21
22
use syntax:: parse:: token:: keywords;
@@ -159,74 +160,51 @@ macro_rules! unpack {
159
160
///////////////////////////////////////////////////////////////////////////
160
161
/// the main entry point for building MIR for a function
161
162
162
- pub fn construct < ' a , ' tcx > ( hir : Cx < ' a , ' tcx > ,
163
- span : Span ,
164
- fn_id : ast:: NodeId ,
165
- body_id : ast:: NodeId ,
166
- implicit_arguments : Vec < Ty < ' tcx > > ,
167
- explicit_arguments : Vec < ( Ty < ' tcx > , & ' tcx hir:: Pat ) > ,
168
- return_ty : FnOutput < ' tcx > ,
169
- ast_block : & ' tcx hir:: Block )
170
- -> ( Mir < ' tcx > , ScopeAuxiliaryVec ) {
163
+ pub fn construct_fn < ' a , ' tcx , A > ( hir : Cx < ' a , ' tcx > ,
164
+ fn_id : ast:: NodeId ,
165
+ arguments : A ,
166
+ return_ty : ty:: FnOutput < ' tcx > ,
167
+ ast_block : & ' tcx hir:: Block )
168
+ -> ( Mir < ' tcx > , ScopeAuxiliaryVec )
169
+ where A : Iterator < Item =( Ty < ' tcx > , Option < & ' tcx hir:: Pat > ) >
170
+ {
171
171
let tcx = hir. tcx ( ) ;
172
- let cfg = CFG { basic_blocks : vec ! [ ] } ;
173
-
174
- let mut builder = Builder {
175
- hir : hir,
176
- cfg : cfg,
177
- fn_span : span,
178
- scopes : vec ! [ ] ,
179
- scope_datas : vec ! [ ] ,
180
- scope_auxiliary : ScopeAuxiliaryVec { vec : vec ! [ ] } ,
181
- loop_scopes : vec ! [ ] ,
182
- temp_decls : vec ! [ ] ,
183
- var_decls : vec ! [ ] ,
184
- var_indices : FnvHashMap ( ) ,
185
- unit_temp : None ,
186
- cached_resume_block : None ,
187
- cached_return_block : None
188
- } ;
189
-
190
- assert_eq ! ( builder. cfg. start_new_block( ) , START_BLOCK ) ;
172
+ let span = tcx. map . span ( fn_id) ;
173
+ let mut builder = Builder :: new ( hir, span) ;
191
174
192
- let mut arg_decls = None ; // assigned to `Some` in closures below
175
+ let body_id = ast_block . id ;
193
176
let call_site_extent =
194
177
tcx. region_maps . lookup_code_extent (
195
178
CodeExtentData :: CallSiteScope { fn_id : fn_id, body_id : body_id } ) ;
196
- let _ = builder. in_scope ( call_site_extent, START_BLOCK , |builder, call_site_scope_id| {
197
- let mut block = START_BLOCK ;
198
- let arg_extent =
199
- tcx. region_maps . lookup_code_extent (
200
- CodeExtentData :: ParameterScope { fn_id : fn_id, body_id : body_id } ) ;
201
- unpack ! ( block = builder. in_scope( arg_extent, block, |builder, arg_scope_id| {
202
- arg_decls = Some ( unpack!( block = builder. args_and_body( block,
203
- return_ty,
204
- implicit_arguments,
205
- explicit_arguments,
206
- arg_scope_id,
207
- ast_block) ) ) ;
208
- block. unit( )
179
+ let arg_extent =
180
+ tcx. region_maps . lookup_code_extent (
181
+ CodeExtentData :: ParameterScope { fn_id : fn_id, body_id : body_id } ) ;
182
+ let mut block = START_BLOCK ;
183
+ let mut arg_decls = unpack ! ( block = builder. in_scope( call_site_extent, block,
184
+ |builder, call_site_scope_id| {
185
+ let arg_decls = unpack!( block = builder. in_scope( arg_extent, block,
186
+ |builder, arg_scope_id| {
187
+ builder. args_and_body( block, return_ty, arguments, arg_scope_id, ast_block)
209
188
} ) ) ;
210
189
211
190
let return_block = builder. return_block( ) ;
212
191
builder. cfg. terminate( block, call_site_scope_id, span,
213
192
TerminatorKind :: Goto { target: return_block } ) ;
214
193
builder. cfg. terminate( return_block, call_site_scope_id, span,
215
194
TerminatorKind :: Return ) ;
216
- return_block. unit ( )
217
- } ) ;
218
-
219
- assert ! (
220
- builder. cfg. basic_blocks
221
- . iter( )
222
- . enumerate( )
223
- . all( |( index, block) | {
224
- if block. terminator. is_none( ) {
225
- bug!( "no terminator on block {:?} in fn {:?}" ,
226
- index, fn_id)
227
- }
228
- true
229
- } ) ) ;
195
+ return_block. and( arg_decls)
196
+ } ) ) ;
197
+ assert_eq ! ( block, builder. return_block( ) ) ;
198
+
199
+ match tcx. node_id_to_type ( fn_id) . sty {
200
+ ty:: TyFnDef ( _, _, f) if f. abi == Abi :: RustCall => {
201
+ // RustCall pseudo-ABI untuples the last argument.
202
+ if let Some ( arg_decl) = arg_decls. last_mut ( ) {
203
+ arg_decl. spread = true ;
204
+ }
205
+ }
206
+ _ => { }
207
+ }
230
208
231
209
// Gather the upvars of a closure, if any.
232
210
let upvar_decls: Vec < _ > = tcx. with_freevars ( fn_id, |freevars| {
@@ -251,72 +229,98 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
251
229
} ) . collect ( )
252
230
} ) ;
253
231
254
- (
255
- Mir {
256
- basic_blocks : builder. cfg . basic_blocks ,
257
- scopes : builder. scope_datas ,
258
- var_decls : builder. var_decls ,
259
- arg_decls : arg_decls. take ( ) . expect ( "args never built?" ) ,
260
- temp_decls : builder. temp_decls ,
261
- upvar_decls : upvar_decls,
262
- return_ty : return_ty,
263
- span : span
264
- } ,
265
- builder. scope_auxiliary ,
266
- )
232
+ builder. finish ( upvar_decls, arg_decls, return_ty)
267
233
}
268
234
269
235
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
270
- fn args_and_body ( & mut self ,
271
- mut block : BasicBlock ,
272
- return_ty : FnOutput < ' tcx > ,
273
- implicit_arguments : Vec < Ty < ' tcx > > ,
274
- explicit_arguments : Vec < ( Ty < ' tcx > , & ' tcx hir:: Pat ) > ,
275
- argument_scope_id : ScopeId ,
276
- ast_block : & ' tcx hir:: Block )
277
- -> BlockAnd < Vec < ArgDecl < ' tcx > > >
236
+ fn new ( hir : Cx < ' a , ' tcx > , span : Span ) -> Builder < ' a , ' tcx > {
237
+ let mut builder = Builder {
238
+ hir : hir,
239
+ cfg : CFG { basic_blocks : vec ! [ ] } ,
240
+ fn_span : span,
241
+ scopes : vec ! [ ] ,
242
+ scope_datas : vec ! [ ] ,
243
+ scope_auxiliary : ScopeAuxiliaryVec { vec : vec ! [ ] } ,
244
+ loop_scopes : vec ! [ ] ,
245
+ temp_decls : vec ! [ ] ,
246
+ var_decls : vec ! [ ] ,
247
+ var_indices : FnvHashMap ( ) ,
248
+ unit_temp : None ,
249
+ cached_resume_block : None ,
250
+ cached_return_block : None
251
+ } ;
252
+
253
+ assert_eq ! ( builder. cfg. start_new_block( ) , START_BLOCK ) ;
254
+
255
+ builder
256
+ }
257
+
258
+ fn finish ( self ,
259
+ upvar_decls : Vec < UpvarDecl > ,
260
+ arg_decls : Vec < ArgDecl < ' tcx > > ,
261
+ return_ty : ty:: FnOutput < ' tcx > )
262
+ -> ( Mir < ' tcx > , ScopeAuxiliaryVec ) {
263
+ for ( index, block) in self . cfg . basic_blocks . iter ( ) . enumerate ( ) {
264
+ if block. terminator . is_none ( ) {
265
+ span_bug ! ( self . fn_span, "no terminator on block {:?}" , index) ;
266
+ }
267
+ }
268
+
269
+ ( Mir {
270
+ basic_blocks : self . cfg . basic_blocks ,
271
+ scopes : self . scope_datas ,
272
+ var_decls : self . var_decls ,
273
+ arg_decls : arg_decls,
274
+ temp_decls : self . temp_decls ,
275
+ upvar_decls : upvar_decls,
276
+ return_ty : return_ty,
277
+ span : self . fn_span
278
+ } , self . scope_auxiliary )
279
+ }
280
+
281
+ fn args_and_body < A > ( & mut self ,
282
+ mut block : BasicBlock ,
283
+ return_ty : ty:: FnOutput < ' tcx > ,
284
+ arguments : A ,
285
+ argument_scope_id : ScopeId ,
286
+ ast_block : & ' tcx hir:: Block )
287
+ -> BlockAnd < Vec < ArgDecl < ' tcx > > >
288
+ where A : Iterator < Item =( Ty < ' tcx > , Option < & ' tcx hir:: Pat > ) >
278
289
{
279
290
// to start, translate the argument patterns and collect the argument types.
280
- let implicits = implicit_arguments. into_iter ( ) . map ( |ty| ( ty, None ) ) ;
281
- let explicits = explicit_arguments. into_iter ( ) . map ( |( ty, pat) | ( ty, Some ( pat) ) ) ;
282
- let arg_decls =
283
- implicits
284
- . chain ( explicits)
285
- . enumerate ( )
286
- . map ( |( index, ( ty, pattern) ) | {
287
- let lvalue = Lvalue :: Arg ( index as u32 ) ;
288
- if let Some ( pattern) = pattern {
289
- let pattern = self . hir . irrefutable_pat ( pattern) ;
290
- unpack ! ( block = self . lvalue_into_pattern( block,
291
- argument_scope_id,
292
- pattern,
293
- & lvalue) ) ;
294
- }
291
+ let arg_decls = arguments. enumerate ( ) . map ( |( index, ( ty, pattern) ) | {
292
+ let lvalue = Lvalue :: Arg ( index as u32 ) ;
293
+ if let Some ( pattern) = pattern {
294
+ let pattern = self . hir . irrefutable_pat ( pattern) ;
295
+ unpack ! ( block = self . lvalue_into_pattern( block,
296
+ argument_scope_id,
297
+ pattern,
298
+ & lvalue) ) ;
299
+ }
295
300
296
- // Make sure we drop (parts of) the argument even when not matched on.
297
- let argument_extent = self . scope_auxiliary [ argument_scope_id] . extent ;
298
- self . schedule_drop ( pattern. as_ref ( ) . map_or ( ast_block. span , |pat| pat. span ) ,
299
- argument_extent, & lvalue, ty) ;
300
-
301
- let mut name = keywords:: Invalid . name ( ) ;
302
- if let Some ( pat) = pattern {
303
- if let hir:: PatKind :: Ident ( _, ref ident, _) = pat. node {
304
- if pat_is_binding ( & self . hir . tcx ( ) . def_map . borrow ( ) , pat) {
305
- name = ident. node . name ;
306
- }
301
+ // Make sure we drop (parts of) the argument even when not matched on.
302
+ let argument_extent = self . scope_auxiliary [ argument_scope_id] . extent ;
303
+ self . schedule_drop ( pattern. as_ref ( ) . map_or ( ast_block. span , |pat| pat. span ) ,
304
+ argument_extent, & lvalue, ty) ;
305
+
306
+ let mut name = keywords:: Invalid . name ( ) ;
307
+ if let Some ( pat) = pattern {
308
+ if let hir:: PatKind :: Ident ( _, ref ident, _) = pat. node {
309
+ if pat_is_binding ( & self . hir . tcx ( ) . def_map . borrow ( ) , pat) {
310
+ name = ident. node . name ;
307
311
}
308
312
}
313
+ }
309
314
310
- ArgDecl {
311
- ty : ty,
312
- spread : false ,
313
- debug_name : name
314
- }
315
- } )
316
- . collect ( ) ;
315
+ ArgDecl {
316
+ ty : ty,
317
+ spread : false ,
318
+ debug_name : name
319
+ }
320
+ } ) . collect ( ) ;
317
321
318
322
// FIXME(#32959): temporary hack for the issue at hand
319
- let return_is_unit = if let FnOutput :: FnConverging ( t) = return_ty {
323
+ let return_is_unit = if let ty :: FnConverging ( t) = return_ty {
320
324
t. is_nil ( )
321
325
} else {
322
326
false
0 commit comments